mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-10-10 21:03:39 +02:00
cleanup error boundaries
This commit is contained in:
@@ -1,19 +1,24 @@
|
|||||||
import React, { memo } from "react";
|
import React, { memo } from "react";
|
||||||
import { ErrorBoundary as ErrorBoundaryHelper, FallbackProps } from "react-error-boundary";
|
import { ErrorBoundary as ErrorBoundaryHelper, FallbackProps } from "react-error-boundary";
|
||||||
import { Alert, AlertIcon, AlertTitle, AlertDescription } from "@chakra-ui/react";
|
import { Alert, AlertIcon, AlertTitle, AlertDescription } from "@chakra-ui/react";
|
||||||
|
import { NostrEvent } from "nostr-tools";
|
||||||
|
import DebugEventButton from "./debug-modal/debug-event-button";
|
||||||
|
|
||||||
export function ErrorFallback({ error, resetErrorBoundary }: Partial<FallbackProps>) {
|
export function ErrorFallback({ error, event, resetErrorBoundary }: Partial<FallbackProps> & { event?: NostrEvent }) {
|
||||||
return (
|
return (
|
||||||
<Alert status="error">
|
<Alert status="error">
|
||||||
<AlertIcon />
|
<AlertIcon />
|
||||||
<AlertTitle>Something went wrong</AlertTitle>
|
<AlertTitle>Something went wrong</AlertTitle>
|
||||||
<AlertDescription>{error?.message}</AlertDescription>
|
<AlertDescription>{error?.message}</AlertDescription>
|
||||||
|
{event && <DebugEventButton event={event} size="sm" variant="ghost" ml="auto" />}
|
||||||
</Alert>
|
</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ErrorBoundary = memo(({ children, ...props }: { children: React.ReactNode }) => (
|
export const ErrorBoundary = memo(
|
||||||
<ErrorBoundaryHelper FallbackComponent={ErrorFallback} {...props}>
|
({ children, event, ...props }: { children: React.ReactNode; event?: NostrEvent }) => (
|
||||||
{children}
|
<ErrorBoundaryHelper fallbackRender={({ error }) => <ErrorFallback error={error} event={event} />} {...props}>
|
||||||
</ErrorBoundaryHelper>
|
{children}
|
||||||
));
|
</ErrorBoundaryHelper>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
@@ -46,7 +46,7 @@ function TimelineItem({ event, visible, minHeight }: { event: NostrEvent; visibl
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary event={event}>
|
||||||
<Box minHeight={minHeight + "px"} ref={ref}>
|
<Box minHeight={minHeight + "px"} ref={ref}>
|
||||||
{visible && content}
|
{visible && content}
|
||||||
</Box>
|
</Box>
|
||||||
|
@@ -157,7 +157,7 @@ function CommunitiesHomePage() {
|
|||||||
<Flex gap="2" direction="column" w="md" flexShrink={0} hideBelow="xl">
|
<Flex gap="2" direction="column" w="md" flexShrink={0} hideBelow="xl">
|
||||||
<Heading size="md">Joined Communities</Heading>
|
<Heading size="md">Joined Communities</Heading>
|
||||||
{communities.map((community) => (
|
{communities.map((community) => (
|
||||||
<ErrorBoundary key={getEventCoordinate(community)}>
|
<ErrorBoundary key={getEventCoordinate(community)} event={community}>
|
||||||
<CommunityCard community={community} />
|
<CommunityCard community={community} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
@@ -187,7 +187,7 @@ function CommunitiesHomePage() {
|
|||||||
|
|
||||||
<DrawerBody display="flex" flexDirection="column" gap="2" px="4" pt="0" pb="8" overflowY="auto">
|
<DrawerBody display="flex" flexDirection="column" gap="2" px="4" pt="0" pb="8" overflowY="auto">
|
||||||
{communities.map((community) => (
|
{communities.map((community) => (
|
||||||
<ErrorBoundary key={getEventCoordinate(community)}>
|
<ErrorBoundary key={getEventCoordinate(community)} event={community}>
|
||||||
<CommunityCard community={community} flexShrink={0} />
|
<CommunityCard community={community} flexShrink={0} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
|
@@ -132,8 +132,8 @@ function FilesPage() {
|
|||||||
<IntersectionObserverProvider callback={callback}>
|
<IntersectionObserverProvider callback={callback}>
|
||||||
<SimpleGrid minChildWidth="20rem" spacing="2">
|
<SimpleGrid minChildWidth="20rem" spacing="2">
|
||||||
{events.map((event) => (
|
{events.map((event) => (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary key={event.id} event={event}>
|
||||||
<FileType key={event.id} event={event} />
|
<FileType event={event} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
|
@@ -51,7 +51,7 @@ function GoalsBrowsePage() {
|
|||||||
|
|
||||||
<SimpleGrid columns={{ base: 1, lg: 2 }} spacing="2">
|
<SimpleGrid columns={{ base: 1, lg: 2 }} spacing="2">
|
||||||
{goals.map((event) => (
|
{goals.map((event) => (
|
||||||
<ErrorBoundary key={getEventUID(event)}>
|
<ErrorBoundary key={getEventUID(event)} event={event}>
|
||||||
<GoalCard goal={event} />
|
<GoalCard goal={event} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
|
@@ -44,7 +44,7 @@ export default function NotificationsCard({ ...props }: Omit<CardProps, "childre
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardBody overflowX="hidden" overflowY="auto" pt="4" display="flex" flexDirection="column">
|
<CardBody overflowX="hidden" overflowY="auto" pt="4" display="flex" flexDirection="column">
|
||||||
{limit.map((event) => (
|
{limit.map((event) => (
|
||||||
<ErrorBoundary key={getEventUID(event)}>
|
<ErrorBoundary key={getEventUID(event)} event={event}>
|
||||||
<NotificationItem event={event} onClick={handleClick} visible />
|
<NotificationItem event={event} onClick={handleClick} visible />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
|
@@ -76,7 +76,7 @@ function StreamsCardContent({ ...props }: Omit<CardProps, "children">) {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardBody overflowX="hidden" overflowY="auto" pt="4" display="flex" gap="2" flexDirection="column" maxH="50vh">
|
<CardBody overflowX="hidden" overflowY="auto" pt="4" display="flex" gap="2" flexDirection="column" maxH="50vh">
|
||||||
{streams.map((stream) => (
|
{streams.map((stream) => (
|
||||||
<ErrorBoundary key={getEventUID(stream.event)}>
|
<ErrorBoundary key={getEventUID(stream.event)} event={stream.event}>
|
||||||
<LiveStream stream={stream} />
|
<LiveStream stream={stream} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
|
@@ -26,7 +26,7 @@ const MapTimeline = React.memo(({ timeline, focused }: { timeline: TimelineLoade
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{events.map((event) => (
|
{events.map((event) => (
|
||||||
<ErrorBoundary key={event.id}>
|
<ErrorBoundary key={event.id} event={event}>
|
||||||
<RenderEvent event={event} focused={focused === event.id} />
|
<RenderEvent event={event} focused={focused === event.id} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
|
@@ -64,8 +64,8 @@ export default function RelaysView() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2">
|
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2">
|
||||||
{filteredRelays.map((url) => (
|
{filteredRelays.map((url) => (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary key={url}>
|
||||||
<RelayCard key={url} url={url} variant="outline" />
|
<RelayCard url={url} variant="outline" />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
@@ -77,8 +77,8 @@ export default function RelaysView() {
|
|||||||
</Heading>
|
</Heading>
|
||||||
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2">
|
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2">
|
||||||
{discoveredRelays.map((url) => (
|
{discoveredRelays.map((url) => (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary key={url}>
|
||||||
<RelayCard key={url} url={url} variant="outline" />
|
<RelayCard url={url} variant="outline" />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
|
@@ -86,55 +86,3 @@ export default function SettingsView() {
|
|||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// export default function SettingsView() {
|
|
||||||
// const toast = useToast();
|
|
||||||
// const { updateSettings, ...settings } = useAppSettings();
|
|
||||||
|
|
||||||
// const form = useForm({
|
|
||||||
// mode: "all",
|
|
||||||
// values: settings,
|
|
||||||
// resetOptions: {
|
|
||||||
// keepDirty: true,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const saveSettings = form.handleSubmit(async (values) => {
|
|
||||||
// try {
|
|
||||||
// await updateSettings(values);
|
|
||||||
// toast({ title: "Settings saved", status: "success" });
|
|
||||||
// } catch (e) {
|
|
||||||
// if (e instanceof Error) toast({ description: e.message, status: "error" });
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <VerticalPageLayout as="form" onSubmit={saveSettings}>
|
|
||||||
// <FormProvider {...form}>
|
|
||||||
// <Accordion defaultIndex={[]} allowMultiple>
|
|
||||||
// <DisplaySettings />
|
|
||||||
// <PostSettings />
|
|
||||||
// <PerformanceSettings />
|
|
||||||
// <PrivacySettings />
|
|
||||||
// <LightningSettings />
|
|
||||||
// <DatabaseSettings />
|
|
||||||
// </Accordion>
|
|
||||||
// </FormProvider>
|
|
||||||
// <Flex gap="4" padding="4" alignItems="center" wrap="wrap">
|
|
||||||
// <Link isExternal href="https://github.com/hzrd149/nostrudel">
|
|
||||||
// <GithubIcon /> Github
|
|
||||||
// </Link>
|
|
||||||
// <VersionButton />
|
|
||||||
// <Button
|
|
||||||
// ml="auto"
|
|
||||||
// isLoading={form.formState.isLoading || form.formState.isValidating || form.formState.isSubmitting}
|
|
||||||
// isDisabled={!form.formState.isDirty}
|
|
||||||
// colorScheme="primary"
|
|
||||||
// type="submit"
|
|
||||||
// >
|
|
||||||
// Save Settings
|
|
||||||
// </Button>
|
|
||||||
// </Flex>
|
|
||||||
// </VerticalPageLayout>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
@@ -69,7 +69,7 @@ export function DMTimelinePage() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
<IntersectionObserverProvider callback={callback}>
|
<IntersectionObserverProvider callback={callback}>
|
||||||
{dms.map((dm) => (
|
{dms.map((dm) => (
|
||||||
<ErrorBoundary key={dm.id}>
|
<ErrorBoundary key={dm.id} event={dm}>
|
||||||
<DirectMessage dm={dm} />
|
<DirectMessage dm={dm} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
|
@@ -9,6 +9,7 @@ import { useTimelineCurserIntersectionCallback } from "../../hooks/use-timeline-
|
|||||||
import TimelineActionAndStatus from "../../components/timeline/timeline-action-and-status";
|
import TimelineActionAndStatus from "../../components/timeline/timeline-action-and-status";
|
||||||
import VerticalPageLayout from "../../components/vertical-page-layout";
|
import VerticalPageLayout from "../../components/vertical-page-layout";
|
||||||
import ArticleCard from "../articles/components/article-card";
|
import ArticleCard from "../articles/components/article-card";
|
||||||
|
import { ErrorBoundary } from "../../components/error-boundary";
|
||||||
|
|
||||||
export default function UserArticlesTab() {
|
export default function UserArticlesTab() {
|
||||||
const { pubkey } = useOutletContext() as { pubkey: string };
|
const { pubkey } = useOutletContext() as { pubkey: string };
|
||||||
@@ -26,7 +27,9 @@ export default function UserArticlesTab() {
|
|||||||
<IntersectionObserverProvider callback={callback}>
|
<IntersectionObserverProvider callback={callback}>
|
||||||
<VerticalPageLayout>
|
<VerticalPageLayout>
|
||||||
{articles.map((article) => (
|
{articles.map((article) => (
|
||||||
<ArticleCard key={article.id} article={article} />
|
<ErrorBoundary key={article.id} event={article}>
|
||||||
|
<ArticleCard article={article} />
|
||||||
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
<TimelineActionAndStatus timeline={timeline} />
|
<TimelineActionAndStatus timeline={timeline} />
|
||||||
</VerticalPageLayout>
|
</VerticalPageLayout>
|
||||||
|
@@ -23,8 +23,8 @@ export default function UserFollowingTab() {
|
|||||||
return (
|
return (
|
||||||
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2" p="2">
|
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2" p="2">
|
||||||
{sorted.map(({ pubkey, relay }) => (
|
{sorted.map(({ pubkey, relay }) => (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary key={pubkey}>
|
||||||
<UserCard key={pubkey} pubkey={pubkey} relay={relay} />
|
<UserCard pubkey={pubkey} relay={relay} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
|
@@ -82,8 +82,8 @@ const UserRelaysTab = () => {
|
|||||||
</Heading>
|
</Heading>
|
||||||
<VStack divider={<StackDivider />} py="2" align="stretch">
|
<VStack divider={<StackDivider />} py="2" align="stretch">
|
||||||
{Array.from(mailboxes?.inboxes ?? []).map((url) => (
|
{Array.from(mailboxes?.inboxes ?? []).map((url) => (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary key={url}>
|
||||||
<Relay key={url} url={url} reviews={getRelayReviews(url, reviews)} />
|
<Relay url={url} reviews={getRelayReviews(url, reviews)} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
</VStack>
|
</VStack>
|
||||||
@@ -92,8 +92,8 @@ const UserRelaysTab = () => {
|
|||||||
</Heading>
|
</Heading>
|
||||||
<VStack divider={<StackDivider />} py="2" align="stretch">
|
<VStack divider={<StackDivider />} py="2" align="stretch">
|
||||||
{Array.from(mailboxes?.outboxes ?? []).map((url) => (
|
{Array.from(mailboxes?.outboxes ?? []).map((url) => (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary key={url}>
|
||||||
<Relay key={url} url={url} reviews={getRelayReviews(url, reviews)} />
|
<Relay url={url} reviews={getRelayReviews(url, reviews)} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
</VStack>
|
</VStack>
|
||||||
|
@@ -122,7 +122,7 @@ const UserZapsTab = () => {
|
|||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
{events.map((event) => (
|
{events.map((event) => (
|
||||||
<ErrorBoundary key={event.id}>
|
<ErrorBoundary key={event.id} event={event}>
|
||||||
<Zap zapEvent={event} />
|
<Zap zapEvent={event} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
|
@@ -34,8 +34,8 @@ function VideosPage() {
|
|||||||
<IntersectionObserverProvider callback={callback}>
|
<IntersectionObserverProvider callback={callback}>
|
||||||
<SimpleGrid columns={{ base: 1, sm: 2, md: 3, lg: 4, xl: 5 }} spacing="2">
|
<SimpleGrid columns={{ base: 1, sm: 2, md: 3, lg: 4, xl: 5 }} spacing="2">
|
||||||
{videos.map((video) => (
|
{videos.map((video) => (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary key={getEventUID(video)} event={video}>
|
||||||
<VideoCard key={getEventUID(video)} video={video} />
|
<VideoCard video={video} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
))}
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
|
Reference in New Issue
Block a user