mirror of
https://github.com/linkwarden/linkwarden.git
synced 2026-03-03 02:27:00 +00:00
move disableDraggable and user hook out of each card to improve efficiency
This commit is contained in:
@@ -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"))
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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",
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user