fix(nextjs): Fix DND & click event issue on sidepanel
This commit is contained in:
parent
cd1bcb9536
commit
27781ef72b
4 changed files with 39 additions and 71 deletions
|
|
@ -18,13 +18,9 @@ import {
|
|||
} from "../hooks";
|
||||
import { PresentationPageProps } from "../types";
|
||||
import LoadingState from "./LoadingState";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
|
||||
const PresentationPage: React.FC<PresentationPageProps> = ({ presentation_id }) => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const isPresentMode = searchParams.get("mode") === "present";
|
||||
const stream = searchParams.get("stream");
|
||||
|
||||
// State management
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [selectedSlide, setSelectedSlide] = useState(0);
|
||||
|
|
@ -51,6 +47,14 @@ const PresentationPage: React.FC<PresentationPageProps> = ({ presentation_id })
|
|||
setError
|
||||
);
|
||||
|
||||
const {
|
||||
isPresentMode,
|
||||
stream,
|
||||
handleSlideClick,
|
||||
toggleFullscreen,
|
||||
handlePresentExit,
|
||||
handleSlideChange,
|
||||
} = usePresentationNavigation(presentation_id, selectedSlide, setSelectedSlide, setIsFullscreen);
|
||||
|
||||
// Initialize streaming
|
||||
usePresentationStreaming(
|
||||
|
|
@ -63,46 +67,12 @@ const PresentationPage: React.FC<PresentationPageProps> = ({ presentation_id })
|
|||
|
||||
|
||||
|
||||
|
||||
const onSlideChange = (newSlide: number) => {
|
||||
handleSlideChange(newSlide, presentationData);
|
||||
};
|
||||
|
||||
const handleSlideClick = useCallback((index: number) => {
|
||||
console.log("handleSlideClick", index);
|
||||
const slideElement = document.getElementById(`slide-${index}`);
|
||||
if (slideElement) {
|
||||
slideElement.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "center",
|
||||
});
|
||||
setSelectedSlide(index);
|
||||
}
|
||||
}, [setSelectedSlide]);
|
||||
|
||||
const toggleFullscreen = useCallback(() => {
|
||||
if (!document.fullscreenElement) {
|
||||
document.documentElement.requestFullscreen();
|
||||
setIsFullscreen(true);
|
||||
} else {
|
||||
document.exitFullscreen();
|
||||
setIsFullscreen(false);
|
||||
}
|
||||
}, [setIsFullscreen]);
|
||||
|
||||
const handlePresentExit = useCallback(() => {
|
||||
setIsFullscreen(false);
|
||||
router.push(`/presentation?id=${presentation_id}`);
|
||||
}, [router, presentation_id, setIsFullscreen]);
|
||||
|
||||
const handleSlideChange = useCallback((newSlide: number, presentationData: any) => {
|
||||
if (newSlide >= 0 && newSlide < presentationData?.slides.length!) {
|
||||
setSelectedSlide(newSlide);
|
||||
router.push(
|
||||
`/presentation?id=${presentation_id}&mode=present&slide=${newSlide}`,
|
||||
{ scroll: false }
|
||||
);
|
||||
}
|
||||
}, [router, presentation_id, setSelectedSlide]);
|
||||
|
||||
// Presentation Mode View
|
||||
if (isPresentMode) {
|
||||
|
|
@ -110,7 +80,6 @@ const PresentationPage: React.FC<PresentationPageProps> = ({ presentation_id })
|
|||
<PresentationMode
|
||||
slides={presentationData?.slides!}
|
||||
currentSlide={selectedSlide}
|
||||
|
||||
isFullscreen={isFullscreen}
|
||||
onFullscreenToggle={toggleFullscreen}
|
||||
onExit={handlePresentExit}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,11 @@ const SidePanel = ({
|
|||
}, [isMobilePanelOpen]);
|
||||
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor),
|
||||
useSensor(PointerSensor, {
|
||||
activationConstraint: {
|
||||
distance: 8, // Start drag after moving 8px
|
||||
},
|
||||
}),
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useSortable } from '@dnd-kit/sortable';
|
||||
import { CSS } from '@dnd-kit/utilities';
|
||||
import { Slide } from '../../types/slide';
|
||||
import { useState } from 'react';
|
||||
import { useRef } from 'react';
|
||||
|
||||
interface SortableListItemProps {
|
||||
slide: Slide;
|
||||
|
|
@ -11,7 +11,7 @@ interface SortableListItemProps {
|
|||
}
|
||||
|
||||
export function SortableListItem({ slide, index, selectedSlide, onSlideClick }: SortableListItemProps) {
|
||||
const [mouseDownTime, setMouseDownTime] = useState(0);
|
||||
const lastClickTime = useRef(0);
|
||||
|
||||
const {
|
||||
attributes,
|
||||
|
|
@ -28,16 +28,17 @@ export function SortableListItem({ slide, index, selectedSlide, onSlideClick }:
|
|||
opacity: isDragging ? 0.5 : 1
|
||||
};
|
||||
|
||||
const handleMouseDown = () => {
|
||||
setMouseDownTime(Date.now());
|
||||
};
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
const now = Date.now();
|
||||
|
||||
const handleMouseUp = () => {
|
||||
const mouseUpTime = Date.now();
|
||||
const timeDiff = mouseUpTime - mouseDownTime;
|
||||
// Debounce clicks - only allow one click every 300ms
|
||||
if (now - lastClickTime.current < 300) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the mouse was down for less than 200ms, consider it a click
|
||||
if (timeDiff < 200 && !isDragging) {
|
||||
// Only trigger click if not dragging
|
||||
if (!isDragging) {
|
||||
lastClickTime.current = now;
|
||||
onSlideClick(slide.index);
|
||||
}
|
||||
};
|
||||
|
|
@ -48,8 +49,7 @@ export function SortableListItem({ slide, index, selectedSlide, onSlideClick }:
|
|||
style={style}
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
onMouseDown={handleMouseDown}
|
||||
onMouseUp={handleMouseUp}
|
||||
onClick={handleClick}
|
||||
className={`p-3 cursor-pointer ring-0 border-[3px] rounded-lg slide-box
|
||||
${selectedSlide === index
|
||||
? ' border-[#5141e5] '
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useSortable } from '@dnd-kit/sortable';
|
||||
import { CSS } from '@dnd-kit/utilities';
|
||||
import { Slide } from '../../types/slide';
|
||||
import { useState } from 'react';
|
||||
import { useRef } from 'react';
|
||||
|
||||
interface SortableSlideProps {
|
||||
slide: Slide;
|
||||
|
|
@ -12,7 +12,7 @@ interface SortableSlideProps {
|
|||
}
|
||||
|
||||
export function SortableSlide({ slide, index, selectedSlide, onSlideClick, renderSlideContent }: SortableSlideProps) {
|
||||
const [mouseDownTime, setMouseDownTime] = useState(0);
|
||||
const lastClickTime = useRef(0);
|
||||
|
||||
const {
|
||||
attributes,
|
||||
|
|
@ -29,20 +29,17 @@ export function SortableSlide({ slide, index, selectedSlide, onSlideClick, rende
|
|||
opacity: isDragging ? 0.5 : 1
|
||||
};
|
||||
|
||||
const handleMouseDown = () => {
|
||||
console.log("mouse down");
|
||||
setMouseDownTime(Date.now());
|
||||
};
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
const now = Date.now();
|
||||
|
||||
const handleMouseUp = () => {
|
||||
console.log("mouse up");
|
||||
const mouseUpTime = Date.now();
|
||||
const timeDiff = mouseUpTime - mouseDownTime;
|
||||
console.log("timeDiff", timeDiff);
|
||||
// Debounce clicks - only allow one click every 300ms
|
||||
if (now - lastClickTime.current < 300) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the mouse was down for less than 300ms, consider it a click
|
||||
if (timeDiff < 300 && !isDragging) {
|
||||
console.log("clicked");
|
||||
// Only trigger click if not dragging
|
||||
if (!isDragging) {
|
||||
lastClickTime.current = now;
|
||||
onSlideClick(slide.index);
|
||||
}
|
||||
};
|
||||
|
|
@ -53,9 +50,7 @@ export function SortableSlide({ slide, index, selectedSlide, onSlideClick, rende
|
|||
style={style}
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
onMouseDown={handleMouseDown}
|
||||
onMouseUp={handleMouseUp}
|
||||
|
||||
onClick={handleClick}
|
||||
className={` cursor-pointer border-[3px] relative p-1 shadow-lg rounded-md transition-all duration-200 ${selectedSlide === index ? ' border-[#5141e5]' : 'border-gray-300'
|
||||
}`}
|
||||
>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue