diff --git a/src/hooks/useBookmarkDragAndDrop.tsx b/src/hooks/useBookmarkDragAndDrop.tsx
deleted file mode 100644
index 248cad9d..00000000
--- a/src/hooks/useBookmarkDragAndDrop.tsx
+++ /dev/null
@@ -1,201 +0,0 @@
-import {
- DragEndEvent,
- KeyboardSensor,
- MouseSensor,
- TouchSensor,
- useSensor,
- useSensors,
-} from "@dnd-kit/core";
-import {
- arrayMove,
- sortableKeyboardCoordinates,
- useSortable,
-} from "@dnd-kit/sortable";
-import { CSS } from "@dnd-kit/utilities";
-import React, { useEffect, useRef, useState } from "react";
-
-import { WatchedMediaCard } from "@/components/media/WatchedMediaCard";
-import { useBookmarkStore } from "@/stores/bookmarks";
-import { MediaItem } from "@/utils/mediaTypes";
-
-interface SortableMediaCardProps {
- media: MediaItem;
- closable?: boolean;
- onClose?: () => void;
- onShowDetails?: (media: MediaItem) => void;
- editable?: boolean;
- onEdit?: () => void;
- isEditing?: boolean;
-}
-
-export function SortableMediaCard({
- media,
- closable,
- onClose,
- onShowDetails,
- editable,
- onEdit,
- isEditing,
-}: SortableMediaCardProps): JSX.Element {
- const {
- attributes,
- listeners,
- setNodeRef,
- transform,
- transition,
- isDragging,
- } = useSortable({ id: media.id });
-
- const style = {
- transform: CSS.Transform.toString(transform),
- transition,
- opacity: isDragging ? 0.5 : 1,
- };
-
- return (
-
-
-
- );
-}
-
-interface UseBookmarkDragAndDropProps {
- editing: boolean;
- items: MediaItem[];
- groupedItems: Record;
-}
-
-export function useBookmarkDragAndDrop({
- editing,
- items,
- groupedItems,
-}: UseBookmarkDragAndDropProps) {
- const bookmarks = useBookmarkStore((s) => s.bookmarks);
- const updateBookmarkOrder = useBookmarkStore((s) => s.updateBookmarkOrder);
-
- // Drag and drop sensors
- const sensors = useSensors(
- useSensor(TouchSensor, {
- activationConstraint: {
- delay: 75,
- tolerance: 1,
- },
- }),
- useSensor(MouseSensor),
- useSensor(KeyboardSensor, {
- coordinateGetter: sortableKeyboardCoordinates,
- }),
- );
-
- // Track order during editing
- const [orderedItems, setOrderedItems] = useState([]);
- const [orderedGroupedItems, setOrderedGroupedItems] = useState<
- Record
- >({});
- const isApplyingOrderRef = useRef(false);
-
- // Initialize ordered items when entering edit mode
- useEffect(() => {
- if (editing) {
- setOrderedItems([...items]);
- setOrderedGroupedItems({ ...groupedItems });
- isApplyingOrderRef.current = false;
- }
- }, [editing, items, groupedItems]);
-
- // Apply order when exiting edit mode
- useEffect(() => {
- if (!editing && orderedItems.length > 0 && !isApplyingOrderRef.current) {
- isApplyingOrderRef.current = true;
-
- // Apply order for regular items
- const regularOrder = orderedItems
- .filter((item) => {
- const bookmark = bookmarks[item.id];
- return !Array.isArray(bookmark?.group) || bookmark.group.length === 0;
- })
- .map((item) => item.id);
- if (regularOrder.length > 0) {
- updateBookmarkOrder(regularOrder);
- }
-
- // Apply order for grouped items
- Object.entries(orderedGroupedItems).forEach(
- ([_groupName, groupItems]) => {
- const groupOrderIds = groupItems.map((item) => item.id);
- if (groupOrderIds.length > 0) {
- updateBookmarkOrder(groupOrderIds);
- }
- },
- );
-
- // Reset ordered items after a short delay to allow state updates to complete
- setTimeout(() => {
- setOrderedItems([]);
- setOrderedGroupedItems({});
- isApplyingOrderRef.current = false;
- }, 0);
- }
- }, [
- editing,
- orderedItems,
- orderedGroupedItems,
- bookmarks,
- updateBookmarkOrder,
- ]);
-
- const handleDragEnd = (event: DragEndEvent, groupName?: string) => {
- const { active, over } = event;
- if (!over || active.id === over.id) return;
-
- if (groupName) {
- // Handle grouped items
- const currentItems = orderedGroupedItems[groupName] || [];
- const oldIndex = currentItems.findIndex((item) => item.id === active.id);
- const newIndex = currentItems.findIndex((item) => item.id === over.id);
- if (oldIndex !== -1 && newIndex !== -1) {
- const newItems = arrayMove(currentItems, oldIndex, newIndex);
- setOrderedGroupedItems({
- ...orderedGroupedItems,
- [groupName]: newItems,
- });
- }
- } else {
- // Handle regular items
- const currentItems = orderedItems.filter((item) => {
- const bookmark = bookmarks[item.id];
- return !Array.isArray(bookmark?.group) || bookmark.group.length === 0;
- });
- const oldIndex = currentItems.findIndex((item) => item.id === active.id);
- const newIndex = currentItems.findIndex((item) => item.id === over.id);
- if (oldIndex !== -1 && newIndex !== -1) {
- const newItems = arrayMove(currentItems, oldIndex, newIndex);
- // Update orderedItems with the new order
- const otherItems = orderedItems.filter((item) => {
- const bookmark = bookmarks[item.id];
- return Array.isArray(bookmark?.group) && bookmark.group.length > 0;
- });
- setOrderedItems([...newItems, ...otherItems]);
- }
- }
- };
-
- return {
- sensors,
- orderedItems,
- orderedGroupedItems,
- handleDragEnd,
- };
-}
diff --git a/src/pages/parts/home/BookmarksCarousel.tsx b/src/pages/parts/home/BookmarksCarousel.tsx
index 58cea30d..1498d544 100644
--- a/src/pages/parts/home/BookmarksCarousel.tsx
+++ b/src/pages/parts/home/BookmarksCarousel.tsx
@@ -1,5 +1,3 @@
-import { DndContext, closestCenter } from "@dnd-kit/core";
-import { SortableContext, rectSortingStrategy } from "@dnd-kit/sortable";
import React, { useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
@@ -9,6 +7,7 @@ import { EditButtonWithText } from "@/components/buttons/EditButtonWithText";
import { Item } from "@/components/form/SortableList";
import { Icon, Icons } from "@/components/Icon";
import { SectionHeading } from "@/components/layout/SectionHeading";
+import { WatchedMediaCard } from "@/components/media/WatchedMediaCard";
import { EditBookmarkModal } from "@/components/overlays/EditBookmarkModal";
import { EditGroupModal } from "@/components/overlays/EditGroupModal";
import { EditGroupOrderModal } from "@/components/overlays/EditGroupOrderModal";
@@ -16,10 +15,6 @@ import { useModal } from "@/components/overlays/Modal";
import { UserIcon, UserIcons } from "@/components/UserIcon";
import { Flare } from "@/components/utils/Flare";
import { useBackendUrl } from "@/hooks/auth/useBackendUrl";
-import {
- SortableMediaCard,
- useBookmarkDragAndDrop,
-} from "@/hooks/useBookmarkDragAndDrop";
import { useIsMobile } from "@/hooks/useIsMobile";
import { CarouselNavButtons } from "@/pages/discover/components/CarouselNavButtons";
import { useAuthStore } from "@/stores/auth";
@@ -186,14 +181,6 @@ export function BookmarksCarousel({
return { groupedItems: grouped, regularItems: regular };
}, [items, bookmarks, progressItems]);
- // Drag and drop hook
- const { sensors, orderedItems, orderedGroupedItems, handleDragEnd } =
- useBookmarkDragAndDrop({
- editing,
- items,
- groupedItems,
- });
-
// group sorting
const allGroups = useMemo(() => {
const groups = new Set();
@@ -448,50 +435,27 @@ export function BookmarksCarousel({
>
- handleDragEnd(e, section.group)}
- >
- item.id)
- : section.items
- .slice(0, MAX_ITEMS_PER_SECTION)
- .map((item) => item.id)
- }
- strategy={rectSortingStrategy}
- >
- {(editing && orderedGroupedItems[section.group || ""]
- ? orderedGroupedItems[section.group || ""]
- : section.items
- )
- .slice(0, MAX_ITEMS_PER_SECTION)
- .map((media) => (
- ,
- ) => e.preventDefault()}
- className="relative mt-4 group cursor-pointer rounded-xl p-2 bg-transparent transition-colors duration-300 w-[10rem] md:w-[11.5rem] h-auto"
- >
- removeBookmark(media.id)}
- editable={editing}
- onEdit={() => handleEditBookmark(media.id)}
- isEditing={editing}
- />
-
- ))}
-
-
+ {section.items
+ .slice(0, MAX_ITEMS_PER_SECTION)
+ .map((media) => (
+ ) =>
+ e.preventDefault()
+ }
+ className="relative mt-4 group cursor-pointer rounded-xl p-2 bg-transparent transition-colors duration-300 w-[10rem] md:w-[11.5rem] h-auto"
+ >
+ removeBookmark(media.id)}
+ editable={editing}
+ onEdit={() => handleEditBookmark(media.id)}
+ />
+
+ ))}
{section.items.length > MAX_ITEMS_PER_SECTION && (
@@ -545,71 +509,33 @@ export function BookmarksCarousel({
>
- {section.items.length > 0 ? (
- handleDragEnd(e)}
- >
- {
- const bookmark = bookmarks[item.id];
- return (
- !Array.isArray(bookmark?.group) ||
- bookmark.group.length === 0
- );
- })
- .slice(0, MAX_ITEMS_PER_SECTION)
- .map((item) => item.id)
- : section.items
- .slice(0, MAX_ITEMS_PER_SECTION)
- .map((item) => item.id)
- }
- strategy={rectSortingStrategy}
- >
- {(editing
- ? orderedItems.filter((item) => {
- const bookmark = bookmarks[item.id];
- return (
- !Array.isArray(bookmark?.group) ||
- bookmark.group.length === 0
- );
- })
- : section.items
- )
- .slice(0, MAX_ITEMS_PER_SECTION)
- .map((media) => (
- 0
+ ? section.items
+ .slice(0, MAX_ITEMS_PER_SECTION)
+ .map((media) => (
+
,
+ ) => e.preventDefault()}
+ className="relative mt-4 group cursor-pointer rounded-xl p-2 bg-transparent transition-colors duration-300 w-[10rem] md:w-[11.5rem] h-auto"
+ >
+ ,
- ) => e.preventDefault()}
- className="relative mt-4 group cursor-pointer rounded-xl p-2 bg-transparent transition-colors duration-300 w-[10rem] md:w-[11.5rem] h-auto"
- >
- removeBookmark(media.id)}
- editable={editing}
- onEdit={() => handleEditBookmark(media.id)}
- isEditing={editing}
- />
-
- ))}
-
-
- ) : (
- Array.from({ length: SKELETON_COUNT }).map(() => (
-
- ))
- )}
+ media={media}
+ onShowDetails={onShowDetails}
+ closable={editing}
+ onClose={() => removeBookmark(media.id)}
+ editable={editing}
+ onEdit={() => handleEditBookmark(media.id)}
+ />
+
+ ))
+ : Array.from({ length: SKELETON_COUNT }).map(() => (
+
+ ))}
{section.items.length > MAX_ITEMS_PER_SECTION && (
diff --git a/src/pages/parts/home/BookmarksPart.tsx b/src/pages/parts/home/BookmarksPart.tsx
index 84d942d7..97227bf9 100644
--- a/src/pages/parts/home/BookmarksPart.tsx
+++ b/src/pages/parts/home/BookmarksPart.tsx
@@ -1,5 +1,3 @@
-import { DndContext, closestCenter } from "@dnd-kit/core";
-import { SortableContext, rectSortingStrategy } from "@dnd-kit/sortable";
import { useAutoAnimate } from "@formkit/auto-animate/react";
import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
@@ -10,16 +8,13 @@ import { Item } from "@/components/form/SortableList";
import { Icons } from "@/components/Icon";
import { SectionHeading } from "@/components/layout/SectionHeading";
import { MediaGrid } from "@/components/media/MediaGrid";
+import { WatchedMediaCard } from "@/components/media/WatchedMediaCard";
import { EditBookmarkModal } from "@/components/overlays/EditBookmarkModal";
import { EditGroupModal } from "@/components/overlays/EditGroupModal";
import { EditGroupOrderModal } from "@/components/overlays/EditGroupOrderModal";
import { useModal } from "@/components/overlays/Modal";
import { UserIcon, UserIcons } from "@/components/UserIcon";
import { useBackendUrl } from "@/hooks/auth/useBackendUrl";
-import {
- SortableMediaCard,
- useBookmarkDragAndDrop,
-} from "@/hooks/useBookmarkDragAndDrop";
import { useAuthStore } from "@/stores/auth";
import { useBookmarkStore } from "@/stores/bookmarks";
import { useGroupOrderStore } from "@/stores/groupOrder";
@@ -125,14 +120,6 @@ export function BookmarksPart({
return { groupedItems: grouped, regularItems: regular };
}, [items, bookmarks, progressItems]);
- // Drag and drop hook
- const { sensors, orderedItems, orderedGroupedItems, handleDragEnd } =
- useBookmarkDragAndDrop({
- editing,
- items,
- groupedItems,
- });
-
// group sorting
const allGroups = useMemo(() => {
const groups = new Set();
@@ -351,47 +338,26 @@ export function BookmarksPart({
/>
- handleDragEnd(e, section.group)}
- >
- item.id,
- )
- : section.items.map((item) => item.id)
- }
- strategy={rectSortingStrategy}
- >
-
- {(editing && orderedGroupedItems[section.group || ""]
- ? orderedGroupedItems[section.group || ""]
- : section.items
- ).map((v) => (
- ) =>
- e.preventDefault()
- }
- className="relative group"
- >
- removeBookmark(v.id)}
- onShowDetails={onShowDetails}
- editable={editing}
- onEdit={() => handleEditBookmark(v.id)}
- isEditing={editing}
- />
-
- ))}
-
-
-
+
+ {section.items.map((v) => (
+ ) =>
+ e.preventDefault()
+ }
+ className="relative group"
+ >
+ removeBookmark(v.id)}
+ onShowDetails={onShowDetails}
+ editable={editing}
+ onEdit={() => handleEditBookmark(v.id)}
+ />
+
+ ))}
+
);
} // regular items
@@ -418,59 +384,26 @@ export function BookmarksPart({
/>
- handleDragEnd(e)}
- >
- {
- const bookmark = bookmarks[item.id];
- return (
- !Array.isArray(bookmark?.group) ||
- bookmark.group.length === 0
- );
- })
- .map((item) => item.id)
- : section.items.map((item) => item.id)
- }
- strategy={rectSortingStrategy}
- >
-
- {(editing
- ? orderedItems.filter((item) => {
- const bookmark = bookmarks[item.id];
- return (
- !Array.isArray(bookmark?.group) ||
- bookmark.group.length === 0
- );
- })
- : section.items
- ).map((v) => (
- ) =>
- e.preventDefault()
- }
- className="relative group"
- >
- removeBookmark(v.id)}
- onShowDetails={onShowDetails}
- editable={editing}
- onEdit={() => handleEditBookmark(v.id)}
- isEditing={editing}
- />
-
- ))}
-
-
-
+
+ {section.items.map((v) => (
+ ) =>
+ e.preventDefault()
+ }
+ className="relative group"
+ >
+ removeBookmark(v.id)}
+ onShowDetails={onShowDetails}
+ editable={editing}
+ onEdit={() => handleEditBookmark(v.id)}
+ />
+
+ ))}
+
);
})}
diff --git a/src/stores/bookmarks/index.ts b/src/stores/bookmarks/index.ts
index 7df352c4..9e048fc3 100644
--- a/src/stores/bookmarks/index.ts
+++ b/src/stores/bookmarks/index.ts
@@ -54,7 +54,6 @@ export interface BookmarkStore {
modifyBookmarksByGroup(
options: BulkGroupModificationOptions,
): BookmarkModificationResult;
- updateBookmarkOrder(bookmarkIds: string[]): void;
clear(): void;
clearUpdateQueue(): void;
removeUpdateItem(id: string): void;
@@ -278,21 +277,6 @@ export const useBookmarkStore = create(
return result;
},
- updateBookmarkOrder(bookmarkIds: string[]) {
- set((s) => {
- const baseTime = Date.now();
- bookmarkIds.forEach((bookmarkId, index) => {
- const bookmark = s.bookmarks[bookmarkId];
- if (bookmark) {
- // Update timestamp to reflect order (earlier items have higher timestamps)
- // This ensures they appear first when sorted by date descending
- // Note: We don't add to update queue here to avoid quota errors.
- // Order is persisted locally via updatedAt timestamps.
- bookmark.updatedAt = baseTime - index;
- }
- });
- });
- },
})),
{
name: "__MW::bookmarks",