move disableDraggable and user hook out of each card to improve efficiency

This commit is contained in:
daniel31x13
2025-12-14 18:20:57 -05:00
parent 1e515d5284
commit 40c3ccca93
5 changed files with 73 additions and 57 deletions

View File

@@ -14,10 +14,8 @@ import {
formatAvailable,
} from "@linkwarden/lib/formatStats";
import LinkIcon from "./LinkIcon";
import usePermissions from "@/hooks/usePermissions";
import toast from "react-hot-toast";
import LinkTypeBadge from "./LinkTypeBadge";
import { useUser } from "@linkwarden/router/user";
import useLocalSettingsStore from "@/store/localSettings";
import LinkPin from "./LinkPin";
import LinkFormats from "./LinkFormats";
@@ -25,7 +23,6 @@ import openLink from "@/lib/client/openLink";
import { Separator } from "@/components/ui/separator";
import { useDraggable } from "@dnd-kit/core";
import { cn } from "@/lib/utils";
import useMediaQuery from "@/hooks/useMediaQuery";
import { TFunction } from "i18next";
type Props = {
@@ -33,6 +30,8 @@ type Props = {
collection: CollectionIncludingMembersAndLinkCount;
isPublicRoute: boolean;
t: TFunction<"translation", undefined>;
user: any;
disableDraggable: boolean;
isSelected: boolean;
toggleSelected: (id: number) => void;
imageHeightClass: string;
@@ -44,36 +43,29 @@ export default function LinkCard({
collection,
isPublicRoute,
t,
user,
disableDraggable,
isSelected,
toggleSelected,
imageHeightClass,
editMode,
}: Props) {
// we don't want to use the draggable feature for screen under 1023px since the sidebar is hidden
const isSmallScreen = useMediaQuery("(max-width: 1023px)");
const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
id: link.id?.toString() ?? "",
data: {
linkId: link.id,
},
disabled: isSmallScreen,
disabled: disableDraggable,
});
const { data: user } = useUser();
const {
settings: { show },
} = useLocalSettingsStore();
const ref = useRef<HTMLDivElement>(null);
const permissions = usePermissions(collection?.id as number);
const [linkModal, setLinkModal] = useState(false);
const selectable =
editMode &&
(permissions === true || permissions?.canCreate || permissions?.canDelete);
return (
<div
ref={setNodeRef}
@@ -84,7 +76,7 @@ export default function LinkCard({
"relative group touch-manipulation select-none"
)}
onClick={() =>
selectable
editMode
? toggleSelected(link.id as number)
: editMode
? toast.error(t("link_selection_error"))

View File

@@ -9,17 +9,14 @@ import LinkDate from "@/components/LinkViews/LinkComponents/LinkDate";
import LinkCollection from "@/components/LinkViews/LinkComponents/LinkCollection";
import LinkIcon from "@/components/LinkViews/LinkComponents/LinkIcon";
import { cn, isPWA } from "@/lib/utils";
import usePermissions from "@/hooks/usePermissions";
import toast from "react-hot-toast";
import LinkTypeBadge from "./LinkTypeBadge";
import { useUser } from "@linkwarden/router/user";
import useLocalSettingsStore from "@/store/localSettings";
import LinkPin from "./LinkPin";
import { atLeastOneFormatAvailable } from "@linkwarden/lib/formatStats";
import LinkFormats from "./LinkFormats";
import openLink from "@/lib/client/openLink";
import { useDraggable } from "@dnd-kit/core";
import useMediaQuery from "@/hooks/useMediaQuery";
import { TFunction } from "i18next";
type Props = {
@@ -27,6 +24,8 @@ type Props = {
collection: CollectionIncludingMembersAndLinkCount;
isPublicRoute: boolean;
t: TFunction<"translation", undefined>;
disableDraggable: boolean;
user: any;
isSelected: boolean;
toggleSelected: (id: number) => void;
count: number;
@@ -39,31 +38,24 @@ export default function LinkList({
collection,
isPublicRoute,
t,
disableDraggable,
user,
isSelected,
toggleSelected,
editMode,
}: Props) {
const isSmallScreen = useMediaQuery("(max-width: 1023px)");
const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
id: link.id?.toString() ?? "",
data: {
linkId: link.id,
},
disabled: isSmallScreen,
disabled: disableDraggable,
});
const { data: user } = useUser();
const {
settings: { show },
} = useLocalSettingsStore();
const permissions = usePermissions(collection?.id as number);
const selectable =
editMode &&
(permissions === true || permissions?.canCreate || permissions?.canDelete);
const [linkModal, setLinkModal] = useState(false);
return (
@@ -80,7 +72,7 @@ export default function LinkList({
"duration-200, touch-manipulation select-none"
)}
onClick={() =>
selectable
editMode
? toggleSelected(link.id as number)
: editMode
? toast.error(t("link_selection_error"))

View File

@@ -15,10 +15,8 @@ import {
} from "@linkwarden/lib/formatStats";
import Link from "next/link";
import LinkIcon from "./LinkIcon";
import usePermissions from "@/hooks/usePermissions";
import toast from "react-hot-toast";
import LinkTypeBadge from "./LinkTypeBadge";
import { useUser } from "@linkwarden/router/user";
import useLocalSettingsStore from "@/store/localSettings";
import clsx from "clsx";
import LinkPin from "./LinkPin";
@@ -27,7 +25,6 @@ import openLink from "@/lib/client/openLink";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
import { useDraggable } from "@dnd-kit/core";
import useMediaQuery from "@/hooks/useMediaQuery";
import { cn } from "@linkwarden/lib";
import { TFunction } from "i18next";
@@ -36,6 +33,8 @@ type Props = {
collection: CollectionIncludingMembersAndLinkCount;
isPublicRoute: boolean;
t: TFunction<"translation", undefined>;
disableDraggable: boolean;
user: any;
isSelected: boolean;
toggleSelected: (id: number) => void;
imageHeightClass: string;
@@ -47,33 +46,26 @@ export default function LinkMasonry({
collection,
isPublicRoute,
t,
disableDraggable,
user,
isSelected,
toggleSelected,
imageHeightClass,
editMode,
}: Props) {
// we don't want to use the draggable feature for screen under 1023px since the sidebar is hidden
const isSmallScreen = useMediaQuery("(max-width: 1023px)");
const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
id: link.id?.toString() ?? "",
data: {
linkId: link.id,
},
disabled: isSmallScreen,
disabled: disableDraggable,
});
const { data: user } = useUser();
const {
settings: { show },
} = useLocalSettingsStore();
const ref = useRef<HTMLDivElement>(null);
const permissions = usePermissions(collection?.id as number);
const selectable =
editMode &&
(permissions === true || permissions?.canCreate || permissions?.canDelete);
const [linkModal, setLinkModal] = useState(false);
@@ -85,7 +77,7 @@ export default function LinkMasonry({
isSelected && "border-primary bg-base-300"
)}
onClick={() =>
selectable
editMode
? toggleSelected(link.id as number)
: editMode
? toast.error(t("link_selection_error"))

View File

@@ -16,12 +16,16 @@ import { useRouter } from "next/router";
import { useTranslation } from "next-i18next";
import { TFunction } from "i18next";
import useLinkStore from "@/store/links";
import useMediaQuery from "@/hooks/useMediaQuery";
import { useUser } from "@linkwarden/router/user";
function CardView({
links,
collectionsById,
isPublicRoute,
t,
user,
disableDraggable,
isSelected,
toggleSelected,
editMode,
@@ -33,6 +37,8 @@ function CardView({
collectionsById: Map<number, CollectionIncludingMembersAndLinkCount>;
isPublicRoute: boolean;
t: TFunction<"translation", undefined>;
user: any;
disableDraggable: boolean;
isSelected: (id: number) => boolean;
toggleSelected: (id: number) => void;
editMode: boolean;
@@ -122,6 +128,8 @@ function CardView({
collection={collection as CollectionIncludingMembersAndLinkCount}
isPublicRoute={isPublicRoute}
t={t}
user={user}
disableDraggable={disableDraggable}
isSelected={selected}
toggleSelected={toggleSelected}
editMode={editMode}
@@ -148,6 +156,8 @@ function MasonryView({
collectionsById,
isPublicRoute,
t,
disableDraggable,
user,
isSelected,
toggleSelected,
editMode,
@@ -159,6 +169,8 @@ function MasonryView({
collectionsById: Map<number, CollectionIncludingMembersAndLinkCount>;
isPublicRoute: boolean;
t: TFunction<"translation", undefined>;
disableDraggable: boolean;
user: any;
isSelected: (id: number) => boolean;
toggleSelected: (id: number) => void;
editMode: boolean;
@@ -256,6 +268,8 @@ function MasonryView({
collection={collection as CollectionIncludingMembersAndLinkCount}
isPublicRoute={isPublicRoute}
t={t}
disableDraggable={disableDraggable}
user={user}
isSelected={selected}
toggleSelected={toggleSelected}
imageHeightClass={imageHeightClass}
@@ -282,6 +296,8 @@ function ListView({
collectionsById,
isPublicRoute,
t,
disableDraggable,
user,
isSelected,
toggleSelected,
editMode,
@@ -293,6 +309,8 @@ function ListView({
collectionsById: Map<number, CollectionIncludingMembersAndLinkCount>;
isPublicRoute: boolean;
t: TFunction<"translation", undefined>;
disableDraggable: boolean;
user: any;
isSelected: (id: number) => boolean;
toggleSelected: (id: number) => void;
editMode: boolean;
@@ -313,6 +331,8 @@ function ListView({
collection={collection as CollectionIncludingMembersAndLinkCount}
isPublicRoute={isPublicRoute}
t={t}
disableDraggable={disableDraggable}
user={user}
isSelected={selected}
toggleSelected={toggleSelected}
count={i}
@@ -357,7 +377,7 @@ export default function Links({
if (inView && useData?.fetchNextPage && useData?.hasNextPage) {
useData.fetchNextPage();
}
}, [useData?.fetchNextPage, useData?.hasNextPage, inView]);
}, [useData, inView]);
const { data: collections = [] } = useCollections();
@@ -397,6 +417,10 @@ export default function Links({
};
}, [links]);
const disableDraggable = useMediaQuery("(max-width: 1023px)");
const { data: user } = useUser();
if (layout === ViewMode.List) {
return (
<ListView
@@ -404,6 +428,8 @@ export default function Links({
collectionsById={collectionsById}
isPublicRoute={isPublicRoute}
t={t}
disableDraggable={disableDraggable}
user={user}
toggleSelected={toggleSelected}
isSelected={isSelected}
editMode={editMode || false}
@@ -419,6 +445,8 @@ export default function Links({
collectionsById={collectionsById}
isPublicRoute={isPublicRoute}
t={t}
disableDraggable={disableDraggable}
user={user}
toggleSelected={toggleSelected}
isSelected={isSelected}
editMode={editMode || false}
@@ -435,6 +463,8 @@ export default function Links({
collectionsById={collectionsById}
isPublicRoute={isPublicRoute}
t={t}
user={user}
disableDraggable={disableDraggable}
toggleSelected={toggleSelected}
isSelected={isSelected}
editMode={editMode || false}

View File

@@ -20,15 +20,30 @@ import getFormatFromContentType from "@linkwarden/lib/getFormatFromContentType";
import getLinkTypeFromFormat from "@linkwarden/lib/getLinkTypeFromFormat";
const useLinks = (params: LinkRequestQuery = {}, auth?: MobileAuth) => {
const queryParamsObject = {
sort: params.sort ?? Number(window.localStorage.getItem("sortBy")) ?? 0,
collectionId: params.collectionId,
tagId: params.tagId,
pinnedOnly: params.pinnedOnly ?? undefined,
searchQueryString: params.searchQueryString,
} as LinkRequestQuery;
const sort =
params.sort ??
(typeof window !== "undefined"
? Number(window.localStorage.getItem("sortBy"))
: 0) ??
0;
const queryString = buildQueryString(queryParamsObject);
const queryString = useMemo(() => {
const queryParamsObject: LinkRequestQuery = {
sort,
collectionId: params.collectionId,
tagId: params.tagId,
pinnedOnly: params.pinnedOnly ?? undefined,
searchQueryString: params.searchQueryString,
};
return buildQueryString(queryParamsObject);
}, [
sort,
params.collectionId,
params.tagId,
params.pinnedOnly,
params.searchQueryString,
]);
const { data, ...rest } = useFetchLinks(queryString, auth);
@@ -83,12 +98,7 @@ const useFetchLinks = (params: string, auth?: MobileAuth) => {
},
initialPageParam: 0,
refetchOnWindowFocus: false,
getNextPageParam: (lastPage) => {
if (lastPage.nextCursor === null) {
return undefined;
}
return lastPage.nextCursor;
},
getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
enabled: status === "authenticated",
});
};