Skip to content

Commit

Permalink
client-web: more profile info; event details
Browse files Browse the repository at this point in the history
  • Loading branch information
franzos committed Aug 23, 2023
1 parent 0e55dc9 commit b239d3d
Show file tree
Hide file tree
Showing 15 changed files with 410 additions and 115 deletions.
14 changes: 8 additions & 6 deletions client-web/src/components/bottom-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ export function BottomBar() {

const toast = useToast();

const update = async () => {
const count = await useNClient.getState().countUsers();
if (count) {
setUserCount(count);
}
};

useEffect(() => {
const statsUpdateInterval = setInterval(async () => {
const count = await useNClient.getState().countUsers();
if (count) {
setUserCount(count);
}
}, 1000);
const statsUpdateInterval = setInterval(update, 1000);

return () => clearInterval(statsUpdateInterval);
}, []);
Expand Down
8 changes: 4 additions & 4 deletions client-web/src/components/create-event-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ export const CreateEventForm = () => {
setUserRelayId(tags[1]);
}
const key = tags[0];
const user = await useNClient.getState().getUser(key);
if (user) {
foundUsers.push(user);
const record = await useNClient.getState().getUser(key);
if (record) {
foundUsers.push(record.user);
} else {
foundUsers.push(new NUser({ pubkey: key }));
}
Expand Down Expand Up @@ -223,7 +223,7 @@ export const CreateEventForm = () => {
<FormLabel>Type: {translateNameToLabel(newEventName)}</FormLabel>

{users.map((user) => (
<User user={user} key={user.pubkey} relayId={userRelayId} />
<User user={user} key={user.pubkey} relayIds={[userRelayId]} />
))}
</FormControl>
<FormControl marginBottom={4}>
Expand Down
80 changes: 80 additions & 0 deletions client-web/src/components/event.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
useDisclosure,
ModalFooter,
ModalHeader,
ModalCloseButton,
} from "@chakra-ui/react";
import {
NEvent,
Expand Down Expand Up @@ -80,6 +81,11 @@ export function Event({

// Image handling
const { isOpen, onOpen, onClose } = useDisclosure();
const {
isOpen: isEventModalOpen,
onOpen: onEventModalOpen,
onClose: onEventModalClose,
} = useDisclosure();
const [selectedImage, setSelectedImage] = useState<string | null>(null);

const openImage = (imageSrc: string) => {
Expand Down Expand Up @@ -230,6 +236,70 @@ export function Event({
);
};

function RenderInfoObject({ obj }: { obj: NEvent }) {
if (!obj) return null;

return (
<div>
{Object.entries(obj).map(([key, value]) => {
// If value is an object and not an array, recurse with RenderInfoObject
if (
typeof value === "object" &&
value !== null &&
!Array.isArray(value)
) {
return (
<div key={key}>
<strong>{key}:</strong>
<RenderInfoObject obj={value} />
</div>
);
}

// If value is an array, map over its items and render them
if (Array.isArray(value)) {
return (
<div key={key}>
<strong>{key}:</strong>
<ul>
{value.map((item, index) => (
<li key={index}>
{typeof item === "object" && item !== null ? (
<RenderInfoObject obj={item} />
) : (
item.toString()
)}
</li>
))}
</ul>
</div>
);
}

// For primitives, render them directly
return (
<div key={key}>
<strong>{key}:</strong> {value?.toString()}
</div>
);
})}
</div>
);
}

const EventModal = (
<Modal isOpen={isEventModalOpen} onClose={onEventModalClose} size="xl">
<ModalOverlay />
<ModalContent maxHeight="80vh" maxWidth="80vw">
<ModalHeader>Event</ModalHeader>
<ModalCloseButton />
<ModalBody overflowY="auto">
{event && <RenderInfoObject obj={event} />}
</ModalBody>
</ModalContent>
</Modal>
);

return (
<>
<Card border="1px solid #e1e1e1" overflow="hidden">
Expand Down Expand Up @@ -264,6 +334,15 @@ export function Event({
<HStack>
<ActionButtons />
<Text>Relay {eventRelayIds[0].substring(0, 5)}...</Text>

<Button
size={"sm"}
onClick={() => {
onEventModalOpen();
}}
>
Details
</Button>
</HStack>
</CardFooter>
</Card>
Expand Down Expand Up @@ -298,6 +377,7 @@ export function Event({
</ModalFooter>
</ModalContent>
</Modal>
{EventModal}
</>
);
}
16 changes: 9 additions & 7 deletions client-web/src/components/events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ export function Events(props: {
}
};

const newEvents = async () => {
setMoreEventsCount(0);
await useNClient.getState().clearEvents();
await useNClient.getState().setViewSubscription(props.view, props.filters);
};

return (
<Box maxHeight="80vh" overflowY="auto">
{events.map((event) => {
Expand All @@ -48,14 +54,14 @@ export function Events(props: {
event.user && event.user.pubkey ? (
<props.userComponent
user={event.user}
relayId={event.eventRelayIds[0]}
relayIds={event.eventRelayIds}
/>
) : (
<props.userComponent
user={{
pubkey: event.event.pubkey,
}}
relayId={event.eventRelayIds[0]}
relayIds={event.eventRelayIds}
/>
)
) : undefined
Expand All @@ -72,11 +78,7 @@ export function Events(props: {
<Button flex="1" marginRight={2} onClick={moreEvents}>
Load {MAX_EVENTS} more
</Button>
<Button
flex="1"
marginLeft={2}
onClick={async () => useNClient.getState().clearEvents()}
>
<Button flex="1" marginLeft={2} onClick={newEvents}>
Reset and load new (performance)
</Button>
</Box>
Expand Down
76 changes: 46 additions & 30 deletions client-web/src/components/user.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,24 @@ import {
Text,
Button,
Spacer,
Image,
} from "@chakra-ui/react";
import { UserBase } from "@nostr-ts/common";
import { useNClient } from "../state/client";
import { Link } from "react-router-dom";

export function User({
user,
relayId,
relayIds,
hideFollow,
showBanner,
showAbout,
}: {
user: UserBase;
relayId: string;
relayIds: string[];
hideFollow?: boolean;
showBanner?: boolean;
showAbout?: boolean;
}) {
const [following] = useNClient((state) => [
state.followingUserIds.find((f) => f === user.pubkey),
Expand All @@ -29,37 +34,48 @@ export function User({
data && data.display_name ? data.display_name : "Anonymous";
const name = data && data.name ? data.name : "Anonymous";
const picture = data && data.picture ? data.picture : "/no-image.png";
const banner = data && data.banner ? data.banner : undefined;
const about = data && data.about ? data.about : undefined;

const profileLink = `/p/${relayId}/${user.pubkey}`;
const profileLink = `/p/${user.pubkey}?relays=${relayIds.join(",")}`;
// const mentionsLink = `/mentions/${user.pubkey}?relays=${relayIds.join(",")}`;

return (
<Flex>
<Box mr="3">
<Avatar size="sm" src={picture} />
</Box>
<Box>
<Link to={profileLink}>
<Heading size="sm">{display_name}</Heading>
<Text fontSize="sm">{name}</Text>
</Link>
</Box>
<Spacer />
{!hideFollow && (
<Button
variant="outline"
colorScheme={following ? "red" : "green"}
onClick={() =>
following
? useNClient.getState().unfollowUser(user.pubkey)
: useNClient.getState().followUser({
pubkey: user.pubkey,
relayId,
})
}
>
{following ? "Unfollow" : "Follow"}
</Button>
<>
{showBanner && banner && (
<Box marginBottom={2}>
<Image src={banner} alt="banner" />
</Box>
)}
</Flex>
<Flex>
<Box mr="3">
<Avatar size="sm" src={picture} />
</Box>
<Box>
<Link to={profileLink}>
<Heading size="sm">{display_name}</Heading>
<Text fontSize="sm">{name}</Text>
</Link>
{showAbout && about && <Text fontSize="sm">{about}</Text>}
</Box>
<Spacer />
{!hideFollow && (
<Button
variant="outline"
colorScheme={following ? "red" : "green"}
onClick={() =>
following
? useNClient.getState().unfollowUser(user.pubkey)
: useNClient.getState().followUser({
pubkey: user.pubkey,
relayIds,
})
}
>
{following ? "Unfollow" : "Follow"}
</Button>
)}
</Flex>
</>
);
}
8 changes: 8 additions & 0 deletions client-web/src/layouts/primary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export function PrimaryLayout() {
const { isOpen, onOpen, onClose } = useDisclosure();

const update = async () => {
// if (!connected) return;
const following = await useNClient.getState().getAllUsersFollowing();
if (following) {
setFollowingUsers(following);
Expand Down Expand Up @@ -72,6 +73,13 @@ export function PrimaryLayout() {

{connected && (
<>
{/* <MenuItem
label="Mentions"
value={0}
to={`/mentions/${publicKey}`}
leftIcon={<Icon as={AccountMultipleIcon} marginRight={1} />}
/> */}

<MenuItem
label="Following"
value={followingUsers.length}
Expand Down
3 changes: 2 additions & 1 deletion client-web/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
<Route path="/" element={<WelcomeRoute />} />
<Route path="/account" element={<AccountRoute />} />
<Route path="/following" element={<FollowingRoute />} />
{/* <Route path="/mentions/:pubkey" element={<UserMentionsRoute />} /> */}
<Route path="/subscriptions" element={<SubscriptionsRoute />} />
<Route path="/relays" element={<RelaysRoute />} />
<Route path="/queue" element={<PublishingQueueRoute />} />
<Route path="/p/:relayid/:pubkey" element={<UserProfileRoute />} />
<Route path="/p/:pubkey" element={<UserProfileRoute />} />
</Route>
</Routes>
</BrowserRouter>
Expand Down
9 changes: 1 addition & 8 deletions client-web/src/routes/following.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,6 @@ export function FollowingRoute() {

const initDone = useRef<boolean>(false);

const relayId = (relayIds: string[]) => {
if (relayIds && relayIds.length > 0) {
return relayIds[0];
}
return "";
};

useEffect(() => {
const init = async () => {
if (initDone.current) return;
Expand All @@ -43,7 +36,7 @@ export function FollowingRoute() {
<User
user={item.user}
key={item.user.pubkey}
relayId={relayId(item.relayIds)}
relayIds={item.relayIds}
/>
</Box>
))}
Expand Down
Loading

0 comments on commit b239d3d

Please sign in to comment.