mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-09-20 04:20:39 +02:00
fix issue with breakpoints causing re-render
This commit is contained in:
@@ -16,8 +16,11 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cashu/cashu-ts": "^0.8.2-rc.7",
|
"@cashu/cashu-ts": "^0.8.2-rc.7",
|
||||||
"@chakra-ui/anatomy": "^2.2.1",
|
"@chakra-ui/anatomy": "^2.2.1",
|
||||||
|
"@chakra-ui/breakpoint-utils": "^2.0.8",
|
||||||
"@chakra-ui/icons": "^2.1.1",
|
"@chakra-ui/icons": "^2.1.1",
|
||||||
|
"@chakra-ui/media-query": "^3.3.0",
|
||||||
"@chakra-ui/react": "^2.8.1",
|
"@chakra-ui/react": "^2.8.1",
|
||||||
|
"@chakra-ui/shared-utils": "^2.0.4",
|
||||||
"@chakra-ui/styled-system": "^2.9.1",
|
"@chakra-ui/styled-system": "^2.9.1",
|
||||||
"@emotion/react": "^11.11.1",
|
"@emotion/react": "^11.11.1",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Card, CardBody, CardProps, Flex, Heading, Image, Link, Tag, Text, useBreakpointValue } from "@chakra-ui/react";
|
import { Card, CardBody, CardProps, Flex, Heading, Image, Link, Tag, Text } from "@chakra-ui/react";
|
||||||
import { Link as RouterLink, useNavigate } from "react-router-dom";
|
import { Link as RouterLink, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { parseStreamEvent } from "../../../helpers/nostr/stream";
|
import { parseStreamEvent } from "../../../helpers/nostr/stream";
|
||||||
@@ -8,6 +8,7 @@ import { UserLink } from "../../user-link";
|
|||||||
import { UserAvatar } from "../../user-avatar";
|
import { UserAvatar } from "../../user-avatar";
|
||||||
import useEventNaddr from "../../../hooks/use-event-naddr";
|
import useEventNaddr from "../../../hooks/use-event-naddr";
|
||||||
import Timestamp from "../../timestamp";
|
import Timestamp from "../../timestamp";
|
||||||
|
import { useBreakpointValue } from "../../../providers/breakpoint-provider";
|
||||||
|
|
||||||
export default function EmbeddedStream({ event, ...props }: Omit<CardProps, "children"> & { event: NostrEvent }) {
|
export default function EmbeddedStream({ event, ...props }: Omit<CardProps, "children"> & { event: NostrEvent }) {
|
||||||
const stream = parseStreamEvent(event);
|
const stream = parseStreamEvent(event);
|
||||||
|
@@ -8,7 +8,7 @@ import {
|
|||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { Image, ImageProps, useBreakpointValue } from "@chakra-ui/react";
|
import { Image, ImageProps } from "@chakra-ui/react";
|
||||||
|
|
||||||
import appSettings from "../../services/settings/app-settings";
|
import appSettings from "../../services/settings/app-settings";
|
||||||
import { useTrusted } from "../../providers/trust";
|
import { useTrusted } from "../../providers/trust";
|
||||||
@@ -19,6 +19,7 @@ import { isImageURL } from "../../helpers/url";
|
|||||||
import PhotoGallery, { PhotoWithoutSize } from "../photo-gallery";
|
import PhotoGallery, { PhotoWithoutSize } from "../photo-gallery";
|
||||||
import { NostrEvent } from "../../types/nostr-event";
|
import { NostrEvent } from "../../types/nostr-event";
|
||||||
import useAppSettings from "../../hooks/use-app-settings";
|
import useAppSettings from "../../hooks/use-app-settings";
|
||||||
|
import { useBreakpointValue } from "../../providers/breakpoint-provider";
|
||||||
|
|
||||||
function useElementBlur(initBlur = false): { style: CSSProperties; onClick: MouseEventHandler } {
|
function useElementBlur(initBlur = false): { style: CSSProperties; onClick: MouseEventHandler } {
|
||||||
const [blur, setBlur] = useState(initBlur);
|
const [blur, setBlur] = useState(initBlur);
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Container, Flex, Spacer, useBreakpointValue } from "@chakra-ui/react";
|
import { Container, Flex, Spacer } from "@chakra-ui/react";
|
||||||
import { ErrorBoundary } from "../error-boundary";
|
|
||||||
|
|
||||||
|
import { ErrorBoundary } from "../error-boundary";
|
||||||
import { ReloadPrompt } from "../reload-prompt";
|
import { ReloadPrompt } from "../reload-prompt";
|
||||||
import DesktopSideNav from "./desktop-side-nav";
|
import DesktopSideNav from "./desktop-side-nav";
|
||||||
import MobileBottomNav from "./mobile-bottom-nav";
|
import MobileBottomNav from "./mobile-bottom-nav";
|
||||||
import useSubject from "../../hooks/use-subject";
|
import useSubject from "../../hooks/use-subject";
|
||||||
import accountService from "../../services/account";
|
import accountService from "../../services/account";
|
||||||
import GhostToolbar from "./ghost-toolbar";
|
import GhostToolbar from "./ghost-toolbar";
|
||||||
|
import { useBreakpointValue } from "../../providers/breakpoint-provider";
|
||||||
|
|
||||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
const isMobile = useBreakpointValue({ base: true, md: false });
|
const isMobile = useBreakpointValue({ base: true, md: false });
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
import { ButtonGroup, ButtonGroupProps, Divider, useBreakpointValue } from "@chakra-ui/react";
|
import { ButtonGroup, ButtonGroupProps, Divider } from "@chakra-ui/react";
|
||||||
|
|
||||||
import { NostrEvent } from "../../../types/nostr-event";
|
import { NostrEvent } from "../../../types/nostr-event";
|
||||||
import ReactionButton from "./reaction-button";
|
import ReactionButton from "./reaction-button";
|
||||||
import EventReactionButtons from "../../event-reactions";
|
import EventReactionButtons from "../../event-reactions";
|
||||||
import useEventReactions from "../../../hooks/use-event-reactions";
|
import useEventReactions from "../../../hooks/use-event-reactions";
|
||||||
|
import { useBreakpointValue } from "../../../providers/breakpoint-provider";
|
||||||
|
|
||||||
export default function NoteReactions({ event, ...props }: Omit<ButtonGroupProps, "children"> & { event: NostrEvent }) {
|
export default function NoteReactions({ event, ...props }: Omit<ButtonGroupProps, "children"> & { event: NostrEvent }) {
|
||||||
const reactions = useEventReactions(event.id) ?? [];
|
const reactions = useEventReactions(event.id) ?? [];
|
||||||
|
@@ -11,7 +11,6 @@ import {
|
|||||||
IconButton,
|
IconButton,
|
||||||
Link,
|
Link,
|
||||||
Text,
|
Text,
|
||||||
useBreakpointValue,
|
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { NostrEvent, isATag } from "../../types/nostr-event";
|
import { NostrEvent, isATag } from "../../types/nostr-event";
|
||||||
@@ -44,6 +43,7 @@ import OpenInDrawerButton from "../open-in-drawer-button";
|
|||||||
import { getSharableEventAddress } from "../../helpers/nip19";
|
import { getSharableEventAddress } from "../../helpers/nip19";
|
||||||
import { COMMUNITY_DEFINITION_KIND, getCommunityName } from "../../helpers/nostr/communities";
|
import { COMMUNITY_DEFINITION_KIND, getCommunityName } from "../../helpers/nostr/communities";
|
||||||
import useReplaceableEvent from "../../hooks/use-replaceable-event";
|
import useReplaceableEvent from "../../hooks/use-replaceable-event";
|
||||||
|
import { useBreakpointValue } from "../../providers/breakpoint-provider";
|
||||||
|
|
||||||
export type NoteProps = Omit<CardProps, "children"> & {
|
export type NoteProps = Omit<CardProps, "children"> & {
|
||||||
event: NostrEvent;
|
event: NostrEvent;
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
import { memo } from "react";
|
import { memo } from "react";
|
||||||
import { useBreakpointValue } from "@chakra-ui/react";
|
|
||||||
|
|
||||||
import { getEventRelays } from "../../services/event-relays";
|
import { getEventRelays } from "../../services/event-relays";
|
||||||
import { NostrEvent } from "../../types/nostr-event";
|
import { NostrEvent } from "../../types/nostr-event";
|
||||||
import useSubject from "../../hooks/use-subject";
|
import useSubject from "../../hooks/use-subject";
|
||||||
import { RelayIconStack, RelayIconStackProps } from "../relay-icon-stack";
|
import { RelayIconStack, RelayIconStackProps } from "../relay-icon-stack";
|
||||||
import { getEventUID } from "../../helpers/nostr/events";
|
import { getEventUID } from "../../helpers/nostr/events";
|
||||||
|
import { useBreakpointValue } from "../../providers/breakpoint-provider";
|
||||||
|
|
||||||
export type NoteRelaysProps = {
|
export type NoteRelaysProps = {
|
||||||
event: NostrEvent;
|
event: NostrEvent;
|
||||||
|
@@ -10,9 +10,9 @@ import {
|
|||||||
LinkBox,
|
LinkBox,
|
||||||
LinkOverlay,
|
LinkOverlay,
|
||||||
Text,
|
Text,
|
||||||
useBreakpointValue,
|
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import useOpenGraphData from "../hooks/use-open-graph-data";
|
import useOpenGraphData from "../hooks/use-open-graph-data";
|
||||||
|
import { useBreakpointValue } from "../providers/breakpoint-provider";
|
||||||
|
|
||||||
export default function OpenGraphCard({ url, ...props }: { url: URL } & Omit<CardProps, "children">) {
|
export default function OpenGraphCard({ url, ...props }: { url: URL } & Omit<CardProps, "children">) {
|
||||||
const { value: data } = useOpenGraphData(url);
|
const { value: data } = useOpenGraphData(url);
|
||||||
|
@@ -1,16 +1,7 @@
|
|||||||
import {
|
import { Alert, AlertDescription, AlertIcon, AlertProps, AlertTitle, Button, Spacer, useModal } from "@chakra-ui/react";
|
||||||
Alert,
|
|
||||||
AlertDescription,
|
|
||||||
AlertIcon,
|
|
||||||
AlertProps,
|
|
||||||
AlertTitle,
|
|
||||||
Button,
|
|
||||||
Spacer,
|
|
||||||
useBreakpointValue,
|
|
||||||
useModal,
|
|
||||||
} from "@chakra-ui/react";
|
|
||||||
|
|
||||||
import { useExpand } from "../providers/expanded";
|
import { useExpand } from "../providers/expanded";
|
||||||
|
import { useBreakpointValue } from "../providers/breakpoint-provider";
|
||||||
|
|
||||||
export default function SensitiveContentWarning({ description }: { description: string } & AlertProps) {
|
export default function SensitiveContentWarning({ description }: { description: string } & AlertProps) {
|
||||||
const expand = useExpand();
|
const expand = useExpand();
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import { useMemo, useRef } from "react";
|
import { useMemo, useRef } from "react";
|
||||||
import { useBreakpointValue } from "@chakra-ui/react";
|
|
||||||
import { Kind } from "nostr-tools";
|
import { Kind } from "nostr-tools";
|
||||||
import { Photo } from "react-photo-album";
|
import { Photo } from "react-photo-album";
|
||||||
|
|
||||||
@@ -14,6 +13,7 @@ import PhotoGallery, { PhotoWithoutSize } from "../../photo-gallery";
|
|||||||
import { useRegisterIntersectionEntity } from "../../../providers/intersection-observer";
|
import { useRegisterIntersectionEntity } from "../../../providers/intersection-observer";
|
||||||
import { NostrEvent } from "../../../types/nostr-event";
|
import { NostrEvent } from "../../../types/nostr-event";
|
||||||
import { getEventUID } from "../../../helpers/nostr/events";
|
import { getEventUID } from "../../../helpers/nostr/events";
|
||||||
|
import { useBreakpointValue } from "../../../providers/breakpoint-provider";
|
||||||
|
|
||||||
function GalleryImage({ event, ...props }: EmbeddedImageProps & { event: NostrEvent }) {
|
function GalleryImage({ event, ...props }: EmbeddedImageProps & { event: NostrEvent }) {
|
||||||
const ref = useRef<HTMLImageElement | null>(null);
|
const ref = useRef<HTMLImageElement | null>(null);
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
export function buildAppSelectUrl(identifier: string, select = true) {
|
export function buildAppSelectUrl(identifier: string, select = true) {
|
||||||
return `https://nostrapp.link/main/apps/social#${identifier}` + (select ? "?select=true" : "");
|
return `https://nostrapp.link/#${identifier}` + (select ? "?select=true" : "");
|
||||||
}
|
}
|
||||||
|
79
src/providers/breakpoint-provider.tsx
Normal file
79
src/providers/breakpoint-provider.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import { PropsWithChildren, createContext, useContext } from "react";
|
||||||
|
import { UseBreakpointOptions, useBreakpoint as useBaseBreakpoint, useTheme } from "@chakra-ui/react";
|
||||||
|
import { isObject } from "@chakra-ui/shared-utils";
|
||||||
|
import { arrayToObjectNotation } from "@chakra-ui/breakpoint-utils";
|
||||||
|
import { breakpoints as defaultBreakPoints } from "@chakra-ui/breakpoint-utils";
|
||||||
|
|
||||||
|
// ChakraUIs useBreakpointValue renders twice, once with the fallback value then with the actual breakpoint value
|
||||||
|
// This causes a lot of re-renders and wasted processing.
|
||||||
|
// This provider is designed to solve that by providing the current breakpoint through context
|
||||||
|
|
||||||
|
const BreakpointContext = createContext("base");
|
||||||
|
|
||||||
|
export function useBreakpoint(arg?: string | UseBreakpointOptions) {
|
||||||
|
return useContext(BreakpointContext) ?? (typeof arg === "object" ? arg.fallback : arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copied from https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/media-query/src/media-query.utils.ts
|
||||||
|
export function getClosestValue<T = any>(
|
||||||
|
values: Record<string, T>,
|
||||||
|
breakpoint: string,
|
||||||
|
breakpoints = defaultBreakPoints,
|
||||||
|
) {
|
||||||
|
let index = Object.keys(values).indexOf(breakpoint);
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
return values[breakpoint];
|
||||||
|
}
|
||||||
|
|
||||||
|
let stopIndex = breakpoints.indexOf(breakpoint);
|
||||||
|
|
||||||
|
while (stopIndex >= 0) {
|
||||||
|
const key = breakpoints[stopIndex];
|
||||||
|
|
||||||
|
if (values.hasOwnProperty(key)) {
|
||||||
|
index = stopIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stopIndex -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
const key = breakpoints[index];
|
||||||
|
return values[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copied from https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/media-query/src/use-breakpoint-value.ts
|
||||||
|
export function useBreakpointValue<T = any>(
|
||||||
|
values: Partial<Record<string, T>> | Array<T | null>,
|
||||||
|
arg?: UseBreakpointOptions | string,
|
||||||
|
): T | undefined {
|
||||||
|
const opts = isObject(arg) ? arg : { fallback: arg ?? "base" };
|
||||||
|
// NOTE: get the breakpoint from context instead of calling ChakraUIs useBreakpoint hook
|
||||||
|
const breakpoint = useBreakpoint(opts);
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
if (!breakpoint) return;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the sorted breakpoint keys from the provided breakpoints
|
||||||
|
*/
|
||||||
|
const breakpoints = Array.from(theme.__breakpoints?.keys || []);
|
||||||
|
|
||||||
|
const obj = Array.isArray(values)
|
||||||
|
? Object.fromEntries<any>(
|
||||||
|
Object.entries(arrayToObjectNotation(values, breakpoints)).map(([key, value]) => [key, value]),
|
||||||
|
)
|
||||||
|
: values;
|
||||||
|
|
||||||
|
return getClosestValue(obj, breakpoint, breakpoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function BreakpointProvider({ children }: PropsWithChildren) {
|
||||||
|
const breakpoint = useBaseBreakpoint();
|
||||||
|
|
||||||
|
return <BreakpointContext.Provider value={breakpoint}>{children}</BreakpointContext.Provider>;
|
||||||
|
}
|
@@ -11,6 +11,7 @@ import PostModalProvider from "./post-modal-provider";
|
|||||||
import { DefaultEmojiProvider, UserEmojiProvider } from "./emoji-provider";
|
import { DefaultEmojiProvider, UserEmojiProvider } from "./emoji-provider";
|
||||||
import { UserContactsUserDirectoryProvider } from "./user-directory-provider";
|
import { UserContactsUserDirectoryProvider } from "./user-directory-provider";
|
||||||
import MuteModalProvider from "./mute-modal-provider";
|
import MuteModalProvider from "./mute-modal-provider";
|
||||||
|
import BreakpointProvider from "./breakpoint-provider";
|
||||||
|
|
||||||
// Top level providers, should be render as close to the root as possible
|
// Top level providers, should be render as close to the root as possible
|
||||||
export const GlobalProviders = ({ children }: { children: React.ReactNode }) => {
|
export const GlobalProviders = ({ children }: { children: React.ReactNode }) => {
|
||||||
@@ -30,22 +31,24 @@ export const GlobalProviders = ({ children }: { children: React.ReactNode }) =>
|
|||||||
/** Providers that provider functionality to pages (needs to be rendered under a router) */
|
/** Providers that provider functionality to pages (needs to be rendered under a router) */
|
||||||
export function PageProviders({ children }: { children: React.ReactNode }) {
|
export function PageProviders({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<SigningProvider>
|
<BreakpointProvider>
|
||||||
<DeleteEventProvider>
|
<SigningProvider>
|
||||||
<MuteModalProvider>
|
<DeleteEventProvider>
|
||||||
<InvoiceModalProvider>
|
<MuteModalProvider>
|
||||||
<NotificationTimelineProvider>
|
<InvoiceModalProvider>
|
||||||
<DefaultEmojiProvider>
|
<NotificationTimelineProvider>
|
||||||
<UserEmojiProvider>
|
<DefaultEmojiProvider>
|
||||||
<UserContactsUserDirectoryProvider>
|
<UserEmojiProvider>
|
||||||
<PostModalProvider>{children}</PostModalProvider>
|
<UserContactsUserDirectoryProvider>
|
||||||
</UserContactsUserDirectoryProvider>
|
<PostModalProvider>{children}</PostModalProvider>
|
||||||
</UserEmojiProvider>
|
</UserContactsUserDirectoryProvider>
|
||||||
</DefaultEmojiProvider>
|
</UserEmojiProvider>
|
||||||
</NotificationTimelineProvider>
|
</DefaultEmojiProvider>
|
||||||
</InvoiceModalProvider>
|
</NotificationTimelineProvider>
|
||||||
</MuteModalProvider>
|
</InvoiceModalProvider>
|
||||||
</DeleteEventProvider>
|
</MuteModalProvider>
|
||||||
</SigningProvider>
|
</DeleteEventProvider>
|
||||||
|
</SigningProvider>
|
||||||
|
</BreakpointProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,6 @@ import {
|
|||||||
Heading,
|
Heading,
|
||||||
Spacer,
|
Spacer,
|
||||||
Spinner,
|
Spinner,
|
||||||
useBreakpointValue,
|
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { useParams, Navigate, useSearchParams, useNavigate } from "react-router-dom";
|
import { useParams, Navigate, useSearchParams, useNavigate } from "react-router-dom";
|
||||||
@@ -52,6 +51,7 @@ import StreamZapButton from "../components/stream-zap-button";
|
|||||||
import StreamGoal from "../components/stream-goal";
|
import StreamGoal from "../components/stream-goal";
|
||||||
import StreamShareButton from "../components/stream-share-button";
|
import StreamShareButton from "../components/stream-share-button";
|
||||||
import VerticalPageLayout from "../../../components/vertical-page-layout";
|
import VerticalPageLayout from "../../../components/vertical-page-layout";
|
||||||
|
import { useBreakpointValue } from "../../../providers/breakpoint-provider";
|
||||||
|
|
||||||
function DesktopStreamPage({ stream }: { stream: ParsedStream }) {
|
function DesktopStreamPage({ stream }: { stream: ParsedStream }) {
|
||||||
useAppTitle(stream.title);
|
useAppTitle(stream.title);
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { Flex, Heading, IconButton, Spacer, useBreakpointValue } from "@chakra-ui/react";
|
import { Flex, Heading, IconButton, Spacer } from "@chakra-ui/react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { EditIcon, GhostIcon } from "../../../components/icons";
|
import { EditIcon, GhostIcon } from "../../../components/icons";
|
||||||
import { UserAvatar } from "../../../components/user-avatar";
|
import { UserAvatar } from "../../../components/user-avatar";
|
||||||
import { UserDnsIdentityIcon } from "../../../components/user-dns-identity-icon";
|
import { UserDnsIdentityIcon } from "../../../components/user-dns-identity-icon";
|
||||||
@@ -9,6 +10,7 @@ import { useUserMetadata } from "../../../hooks/use-user-metadata";
|
|||||||
import { UserProfileMenu } from "./user-profile-menu";
|
import { UserProfileMenu } from "./user-profile-menu";
|
||||||
import { UserFollowButton } from "../../../components/user-follow-button";
|
import { UserFollowButton } from "../../../components/user-follow-button";
|
||||||
import accountService from "../../../services/account";
|
import accountService from "../../../services/account";
|
||||||
|
import { useBreakpointValue } from "../../../providers/breakpoint-provider";
|
||||||
|
|
||||||
export default function Header({
|
export default function Header({
|
||||||
pubkey,
|
pubkey,
|
||||||
|
@@ -99,27 +99,10 @@ const UserView = () => {
|
|||||||
const userTopRelays = useUserTopRelays(pubkey, relayCount);
|
const userTopRelays = useUserTopRelays(pubkey, relayCount);
|
||||||
const relayModal = useDisclosure();
|
const relayModal = useDisclosure();
|
||||||
|
|
||||||
const articleCount = useUserEventKindCount(pubkey, Kind.Article);
|
|
||||||
const streamCount = useUserEventKindCount(pubkey, STREAM_KIND);
|
|
||||||
const goalCount = useUserEventKindCount(pubkey, GOAL_KIND);
|
|
||||||
|
|
||||||
const filteredTabs = useMemo(
|
|
||||||
() =>
|
|
||||||
tabs.filter((t) => {
|
|
||||||
if (t.path === "streams" && streamCount === 0) return false;
|
|
||||||
if (t.path === "goals" && goalCount === 0) return false;
|
|
||||||
if (t.path === "articles" && articleCount === 0) return false;
|
|
||||||
return true;
|
|
||||||
}),
|
|
||||||
[streamCount, goalCount, articleCount],
|
|
||||||
);
|
|
||||||
|
|
||||||
const matches = useMatches();
|
const matches = useMatches();
|
||||||
const lastMatch = matches[matches.length - 1];
|
const lastMatch = matches[matches.length - 1];
|
||||||
|
|
||||||
const activeTab = filteredTabs.indexOf(
|
const activeTab = tabs.indexOf(tabs.find((t) => lastMatch.pathname.endsWith(t.path)) ?? tabs[0]);
|
||||||
filteredTabs.find((t) => lastMatch.pathname.endsWith(t.path)) ?? filteredTabs[0],
|
|
||||||
);
|
|
||||||
|
|
||||||
const metadata = useUserMetadata(pubkey, userTopRelays, { alwaysRequest: true });
|
const metadata = useUserMetadata(pubkey, userTopRelays, { alwaysRequest: true });
|
||||||
|
|
||||||
@@ -136,12 +119,12 @@ const UserView = () => {
|
|||||||
flexGrow="1"
|
flexGrow="1"
|
||||||
isLazy
|
isLazy
|
||||||
index={activeTab}
|
index={activeTab}
|
||||||
onChange={(v) => navigate(filteredTabs[v].path, { replace: true })}
|
onChange={(v) => navigate(tabs[v].path, { replace: true })}
|
||||||
colorScheme="primary"
|
colorScheme="primary"
|
||||||
h="full"
|
h="full"
|
||||||
>
|
>
|
||||||
<TabList overflowX="auto" overflowY="hidden" flexShrink={0}>
|
<TabList overflowX="auto" overflowY="hidden" flexShrink={0}>
|
||||||
{filteredTabs.map(({ label }) => (
|
{tabs.map(({ label }) => (
|
||||||
<Tab key={label} whiteSpace="pre">
|
<Tab key={label} whiteSpace="pre">
|
||||||
{label}
|
{label}
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -149,7 +132,7 @@ const UserView = () => {
|
|||||||
</TabList>
|
</TabList>
|
||||||
|
|
||||||
<TabPanels>
|
<TabPanels>
|
||||||
{filteredTabs.map(({ label }) => (
|
{tabs.map(({ label }) => (
|
||||||
<TabPanel key={label} p={0}>
|
<TabPanel key={label} p={0}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<Suspense fallback={<Spinner />}>
|
<Suspense fallback={<Spinner />}>
|
||||||
|
@@ -1033,7 +1033,7 @@
|
|||||||
"@chakra-ui/react-context" "2.1.0"
|
"@chakra-ui/react-context" "2.1.0"
|
||||||
"@chakra-ui/shared-utils" "2.0.5"
|
"@chakra-ui/shared-utils" "2.0.5"
|
||||||
|
|
||||||
"@chakra-ui/breakpoint-utils@2.0.8":
|
"@chakra-ui/breakpoint-utils@2.0.8", "@chakra-ui/breakpoint-utils@^2.0.8":
|
||||||
version "2.0.8"
|
version "2.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/@chakra-ui/breakpoint-utils/-/breakpoint-utils-2.0.8.tgz#750d3712668b69f6e8917b45915cee0e08688eed"
|
resolved "https://registry.yarnpkg.com/@chakra-ui/breakpoint-utils/-/breakpoint-utils-2.0.8.tgz#750d3712668b69f6e8917b45915cee0e08688eed"
|
||||||
integrity sha512-Pq32MlEX9fwb5j5xx8s18zJMARNHlQZH2VH1RZgfgRDpp7DcEgtRW5AInfN5CfqdHLO1dGxA7I3MqEuL5JnIsA==
|
integrity sha512-Pq32MlEX9fwb5j5xx8s18zJMARNHlQZH2VH1RZgfgRDpp7DcEgtRW5AInfN5CfqdHLO1dGxA7I3MqEuL5JnIsA==
|
||||||
@@ -1232,7 +1232,7 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@chakra-ui/live-region/-/live-region-2.1.0.tgz#02b4b1d997075f19a7a9a87187e08c72e82ef0dd"
|
resolved "https://registry.yarnpkg.com/@chakra-ui/live-region/-/live-region-2.1.0.tgz#02b4b1d997075f19a7a9a87187e08c72e82ef0dd"
|
||||||
integrity sha512-ZOxFXwtaLIsXjqnszYYrVuswBhnIHHP+XIgK1vC6DePKtyK590Wg+0J0slDwThUAd4MSSIUa/nNX84x1GMphWw==
|
integrity sha512-ZOxFXwtaLIsXjqnszYYrVuswBhnIHHP+XIgK1vC6DePKtyK590Wg+0J0slDwThUAd4MSSIUa/nNX84x1GMphWw==
|
||||||
|
|
||||||
"@chakra-ui/media-query@3.3.0":
|
"@chakra-ui/media-query@3.3.0", "@chakra-ui/media-query@^3.3.0":
|
||||||
version "3.3.0"
|
version "3.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@chakra-ui/media-query/-/media-query-3.3.0.tgz#40f9151dedb6a7af9df3be0474b59a799c92c619"
|
resolved "https://registry.yarnpkg.com/@chakra-ui/media-query/-/media-query-3.3.0.tgz#40f9151dedb6a7af9df3be0474b59a799c92c619"
|
||||||
integrity sha512-IsTGgFLoICVoPRp9ykOgqmdMotJG0CnPsKvGQeSFOB/dZfIujdVb14TYxDU4+MURXry1MhJ7LzZhv+Ml7cr8/g==
|
integrity sha512-IsTGgFLoICVoPRp9ykOgqmdMotJG0CnPsKvGQeSFOB/dZfIujdVb14TYxDU4+MURXry1MhJ7LzZhv+Ml7cr8/g==
|
||||||
@@ -1596,6 +1596,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@chakra-ui/shared-utils/-/shared-utils-2.0.5.tgz#cb2b49705e113853647f1822142619570feba081"
|
resolved "https://registry.yarnpkg.com/@chakra-ui/shared-utils/-/shared-utils-2.0.5.tgz#cb2b49705e113853647f1822142619570feba081"
|
||||||
integrity sha512-4/Wur0FqDov7Y0nCXl7HbHzCg4aq86h+SXdoUeuCMD3dSj7dpsVnStLYhng1vxvlbUnLpdF4oz5Myt3i/a7N3Q==
|
integrity sha512-4/Wur0FqDov7Y0nCXl7HbHzCg4aq86h+SXdoUeuCMD3dSj7dpsVnStLYhng1vxvlbUnLpdF4oz5Myt3i/a7N3Q==
|
||||||
|
|
||||||
|
"@chakra-ui/shared-utils@^2.0.4":
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@chakra-ui/shared-utils/-/shared-utils-2.0.4.tgz#8661f2b48dd93d04151b10a894a4290c9d9a080c"
|
||||||
|
integrity sha512-JGWr+BBj3PXGZQ2gxbKSD1wYjESbYsZjkCeE2nevyVk4rN3amV1wQzCnBAhsuJktMaZD6KC/lteo9ou9QUDzpA==
|
||||||
|
|
||||||
"@chakra-ui/skeleton@2.1.0":
|
"@chakra-ui/skeleton@2.1.0":
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@chakra-ui/skeleton/-/skeleton-2.1.0.tgz#e3b25dd3afa330029d6d63be0f7cb8d44ad25531"
|
resolved "https://registry.yarnpkg.com/@chakra-ui/skeleton/-/skeleton-2.1.0.tgz#e3b25dd3afa330029d6d63be0f7cb8d44ad25531"
|
||||||
|
Reference in New Issue
Block a user