Skip to content

Commit

Permalink
client-web: inline events and users
Browse files Browse the repository at this point in the history
  • Loading branch information
franzos committed Sep 27, 2023
1 parent 144b71a commit 7006ff3
Show file tree
Hide file tree
Showing 14 changed files with 324 additions and 96 deletions.
42 changes: 21 additions & 21 deletions client-web/src/components/bottom-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -228,15 +228,15 @@ export function BottomBar() {
<MenuList>
<MenuItem>
<HStack spacing={2}>
<Text fontSize="sm">Users:</Text>
<Text fontSize="xl">{userCount}</Text>
<Text fontSize="xs">Users:</Text>
<Text fontSize="sm">{userCount}</Text>
</HStack>
</MenuItem>
<MenuItem>
<Link as={NavLink} to="/blocked">
<HStack spacing={2}>
<Text fontSize="sm">Blocked Users:</Text>
<Text fontSize="xl">{blockedUsersCount}</Text>
<Text fontSize="xs">Blocked Users:</Text>
<Text fontSize="sm">{blockedUsersCount}</Text>
</HStack>
</Link>
</MenuItem>
Expand All @@ -247,16 +247,16 @@ export function BottomBar() {
}
>
<HStack spacing={2}>
<Text fontSize="sm">Relays:</Text>
<Text fontSize="xl">{relaysCount}</Text>
<Text fontSize="xs">Relays:</Text>
<Text fontSize="sm">{relaysCount}</Text>
</HStack>
</Link>
</MenuItem>
<MenuItem>
<Link onClick={isQueueOpen ? onQueueClose : onQueueOpen}>
<HStack spacing={2}>
<Text fontSize="sm">Queue:</Text>
<Text fontSize="xl">{queueItemsCount}</Text>
<Text fontSize="xs">Queue:</Text>
<Text fontSize="sm">{queueItemsCount}</Text>
</HStack>
</Link>
</MenuItem>
Expand All @@ -269,8 +269,8 @@ export function BottomBar() {
}
>
<HStack spacing={2}>
<Text fontSize="sm">Subscriptions:</Text>
<Text fontSize="xl">{subscriptionsCount}</Text>
<Text fontSize="xs">Subscriptions:</Text>
<Text fontSize="sm">{subscriptionsCount}</Text>
</HStack>
</Link>
</MenuItem>
Expand All @@ -291,27 +291,27 @@ export function BottomBar() {
<EventFormModal buttonSize="sm" />
<Spacer />
<HStack spacing={2}>
<Text fontSize="sm">Users:</Text>
<Text fontSize="xl">{userCount}</Text>
<Text fontSize="xs">Users:</Text>
<Text fontSize="sm">{userCount}</Text>
</HStack>
<Link as={NavLink} to="/blocked">
<HStack spacing={2}>
<Text fontSize="sm">Blocked Users:</Text>
<Text fontSize="xl">{blockedUsersCount}</Text>
<Text fontSize="xs">Blocked Users:</Text>
<Text fontSize="sm">{blockedUsersCount}</Text>
</HStack>
</Link>
<Link
onClick={isRelayModalOpen ? onRelayModalClose : onRelayModalOpen}
>
<HStack spacing={2}>
<Text fontSize="sm">Relays:</Text>
<Text fontSize="xl">{relaysCount}</Text>
<Text fontSize="xs">Relays:</Text>
<Text fontSize="sm">{relaysCount}</Text>
</HStack>
</Link>
<Link onClick={isQueueOpen ? onQueueClose : onQueueOpen}>
<HStack spacing={2}>
<Text fontSize="sm">Queue:</Text>
<Text fontSize="xl">{queueItemsCount}</Text>
<Text fontSize="xs">Queue:</Text>
<Text fontSize="sm">{queueItemsCount}</Text>
</HStack>
</Link>
<Link
Expand All @@ -322,12 +322,12 @@ export function BottomBar() {
}
>
<HStack spacing={2}>
<Text fontSize="sm">Subscriptions:</Text>
<Text fontSize="xl">{subscriptionsCount}</Text>
<Text fontSize="xs">Subscriptions:</Text>
<Text fontSize="sm">{subscriptionsCount}</Text>
</HStack>
</Link>
<Link href="https://github.com/franzos/nostr-ts">
<Text>NostrOP v{APP_VERSION}</Text>
<Text fontSize="xs">NostrOP v{APP_VERSION}</Text>
</Link>
</>
</HStack>
Expand Down
18 changes: 14 additions & 4 deletions client-web/src/components/event.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
LightProcessedEvent,
UserBase,
extractEventContent,
NOSTR_URL_PREFIX,
} from "@nostr-ts/common";
import { useNClient } from "../state/client";
import { excerpt } from "../lib/excerpt";
Expand Down Expand Up @@ -62,12 +63,19 @@ export function Event({ data, level }: EventProps) {
contentWarning: string | undefined;
images: string[] | undefined;
videos: string[] | undefined;
nurls:
| {
type: NOSTR_URL_PREFIX;
data: string;
}[]
| undefined;
text: string | undefined;
} = {
isLoaded: true,
contentWarning,
images: content.images,
videos: content.videos,
nurls: content.nurls,
text: content.text,
};

Expand All @@ -76,6 +84,7 @@ export function Event({ data, level }: EventProps) {
const userOptions = {
showFollowing: true,
showBlock: true,
showLud: true,
relayUrls: data.eventRelayUrls,
};

Expand Down Expand Up @@ -244,17 +253,18 @@ export function Event({ data, level }: EventProps) {
</Box>
</CardHeader>
{/* BODY */}
<CardBody p={0}>
{contentIsVisible && (

{contentIsVisible && (
<CardBody p={0}>
<Skeleton isLoaded={properties.isLoaded}>
<EventContent
content={
properties.isLoaded ? properties.text : data.event.content
}
/>
</Skeleton>
)}
</CardBody>
</CardBody>
)}
{/* FOOTER */}
<EventCardFooter
isReady={isReady}
Expand Down
22 changes: 4 additions & 18 deletions client-web/src/components/event/clickable-links.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Link } from "@chakra-ui/react";
import { Link as RouterLink } from "react-router-dom";
import { excerpt } from "../../lib/excerpt";
import { OnDemandEvent } from "../on-demand-event";
import { OnDemandUsername } from "../on-demand-username";

interface EventContentWithLinksProps {
text: string;
Expand Down Expand Up @@ -37,28 +39,12 @@ export function EventContentWithLinks({ text }: EventContentWithLinksProps) {
if (noteRegex.test(token)) {
const noteId = token.split(":").pop();
return (
<Link
as={RouterLink}
key={index}
to={`/e/${noteId}`}
color={"gray.500"}
>
{token}
</Link>
noteId && <OnDemandEvent key={index} note={noteId} index={index} />
);
}
if (profileRegex.test(token)) {
const profileId = token.split(":").pop();
return (
<Link
as={RouterLink}
key={index}
to={`/p/${profileId}`}
color={"gray.500"}
>
{token}
</Link>
);
return <OnDemandUsername npub={profileId} key={index} />;
}
if (tagsRegex.test(token)) {
return (
Expand Down
2 changes: 1 addition & 1 deletion client-web/src/components/event/zap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export const Zap = ({
<VStack>
<Text mb={2}>
Request a ligning invoice, pay it with your ligtning wallet, and
enter the bolt11 in the next step.
enter the bolt11 invoice receipt from your wallet in the next step.
</Text>
<InputGroup>
<InputLeftAddon children="Sats" />
Expand Down
82 changes: 82 additions & 0 deletions client-web/src/components/on-demand-event.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { useEffect, useRef, useState } from "react";
import { useNClient } from "../state/client";
import { decodeBech32 } from "@nostr-ts/common";
import { Box, Text } from "@chakra-ui/react";
import { Event } from "./event";

interface OnDemandEventProps {
note: string;
index: number;
}

export function OnDemandEvent({ note, index }: OnDemandEventProps) {
const MAX_RETRIES = 20;
const RETRY_INTERVAL = 1000;

const eventId = useRef("");
const relayUrls = useRef<string[]>([]);

const [connected] = useNClient((state) => [state.connected]);
const [eventData] = useNClient((state) => [
state.events[note] ? state.events[note][0] : null,
]);
const [hasTimeout, setHasTimeout] = useState(false);

const fetchEvent = async (retryCount = 0) => {
if (retryCount > MAX_RETRIES) {
setHasTimeout(true);
return;
}

const event = await useNClient.getState().getEvent(eventId.current, {
view: note,
retryCount,
relayUrls: relayUrls.current,
});

if (!event) {
setTimeout(() => fetchEvent(retryCount + 1), RETRY_INTERVAL);
}
};

useEffect(() => {
// Decode note
try {
const decoded = decodeBech32(note);
for (const item of decoded.tlvItems) {
if (item.type === 0) {
eventId.current = item.value as string;
} else if (item.type === 1) {
relayUrls.current.push(item.value as string);
}
}
} catch (e) {
console.error(e);
return;
}

if (note && connected && (!index || index <= 2)) {
fetchEvent();
}

// return () => {
// useNClient.getState().unsubscribeByToken(note);
// };
}, [note, index, connected]);

return (
<Box p={1} m={1}>
{eventData ? (
<Event data={eventData} level={0} />
) : hasTimeout ? (
<Text fontSize="sm" color="gray.500">
Couldn't find {note}.
</Text>
) : (
<Text fontSize="sm" color="gray.500">
Loading ... {note}
</Text>
)}
</Box>
);
}
80 changes: 80 additions & 0 deletions client-web/src/components/on-demand-username.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { Link } from "@chakra-ui/react";
import { NavLink } from "react-router-dom";
import { useNClient } from "../state/client";
import { UserRecord, decodeBech32 } from "@nostr-ts/common";
import { useEffect, useRef, useState } from "react";
import { excerpt } from "../lib/excerpt";

interface OnDemandUsernameProps {
npub?: string;
}

export function OnDemandUsername({ npub }: OnDemandUsernameProps) {
const [status] = useNClient((state) => [state.status]);

const pubkey = useRef<string | null>(null);
const [username, setUsername] = useState<string>("");
const [profileLink, setProfileLink] = useState<string>("");
const [isLoadingUser, setIsLoadingUser] = useState<boolean>(false);

const usernameFromUser = (record: UserRecord) => {
const data = record.user.data;
return data && data.display_name ? `@${data.display_name}` : "";
};

const fetchUser = async (pk: string, retryCount: number = 0) => {
if (retryCount > 20) {
setIsLoadingUser(false);
return;
}

const user = await useNClient.getState().getUser(pk);

if (user) {
setUsername(usernameFromUser(user));
setIsLoadingUser(false);
} else {
if (retryCount === 2) {
await useNClient.getState().requestInformation(
{
idsOrKeys: [pk],
source: "users",
},
{ timeoutIn: 10000 }
);
}

setTimeout(() => fetchUser(pk, retryCount + 1), 1000);
}
};

useEffect(() => {
if (!npub || !["online", "offline"].includes(status)) return;

try {
const decoded = decodeBech32(npub);
const pkItem = decoded.tlvItems.find((item) => item.type === 0);

if (pkItem) {
pubkey.current = pkItem.value as string;
setProfileLink(`/p/${npub}`);
setIsLoadingUser(true);
fetchUser(pubkey.current);
}
} catch (e) {
console.error("Error decoding bech32:", e);
}
}, [status, npub]);

return (
<>
{npub ? (
<Link as={NavLink} to={profileLink} color={"gray.500"}>
{username === "" || isLoadingUser ? excerpt(npub, 10) : username}
</Link>
) : (
<>...</>
)}
</>
);
}
Loading

0 comments on commit 7006ff3

Please sign in to comment.