link to another pager
This commit is contained in:
@@ -11,6 +11,7 @@ type BookViewerProps = {
|
||||
interface PageFlipAPI {
|
||||
flipNext: () => void;
|
||||
flipPrev: () => void;
|
||||
turnToPage: (page: number) => void;
|
||||
}
|
||||
|
||||
interface FlipBookInstance {
|
||||
@@ -43,14 +44,14 @@ const BookViewer: FC<BookViewerProps> = ({ pages }) => {
|
||||
// react-pageflip شماره صفحه را به صورت 0-based برمیگرداند
|
||||
// اما باید مطمئن شویم که در محدوده معتبر است
|
||||
let pageNum = e.data;
|
||||
|
||||
|
||||
// اگر pageNum منفی است یا بزرگتر از تعداد صفحات، آن را محدود میکنیم
|
||||
if (pageNum < 0) {
|
||||
pageNum = 0;
|
||||
} else if (pageNum >= pages.length) {
|
||||
pageNum = pages.length - 1;
|
||||
}
|
||||
|
||||
|
||||
setCurrentPage(pageNum);
|
||||
}, [pages.length]);
|
||||
|
||||
@@ -66,6 +67,81 @@ const BookViewer: FC<BookViewerProps> = ({ pages }) => {
|
||||
}
|
||||
}, [currentPage]);
|
||||
|
||||
const handleLinkClick = useCallback((linkUrl: string) => {
|
||||
if (linkUrl.startsWith('page://')) {
|
||||
const action = linkUrl.replace('page://', '');
|
||||
const pageFlipAPI = bookRef.current?.pageFlip();
|
||||
|
||||
if (!pageFlipAPI) return;
|
||||
|
||||
if (action === 'next') {
|
||||
goToNextPage();
|
||||
} else if (action === 'prev') {
|
||||
goToPrevPage();
|
||||
} else if (action === 'first') {
|
||||
// رفتن به صفحه اول
|
||||
const flipToFirst = () => {
|
||||
if (currentPage > 0) {
|
||||
pageFlipAPI.flipPrev();
|
||||
setTimeout(() => {
|
||||
setCurrentPage(prev => {
|
||||
if (prev > 1) {
|
||||
flipToFirst();
|
||||
}
|
||||
return prev - 1;
|
||||
});
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
flipToFirst();
|
||||
} else if (action === 'last') {
|
||||
// رفتن به صفحه آخر
|
||||
const lastPageIndex = pages.length - 1;
|
||||
const flipToLast = () => {
|
||||
if (currentPage < lastPageIndex) {
|
||||
pageFlipAPI.flipNext();
|
||||
setTimeout(() => {
|
||||
setCurrentPage(prev => {
|
||||
if (prev < lastPageIndex - 1) {
|
||||
flipToLast();
|
||||
}
|
||||
return prev + 1;
|
||||
});
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
flipToLast();
|
||||
} else {
|
||||
// شماره صفحه مشخص (مثل page://3)
|
||||
const pageNum = parseInt(action, 10);
|
||||
if (!isNaN(pageNum) && pageNum >= 1 && pageNum <= pages.length) {
|
||||
const targetIndex = pageNum - 1;
|
||||
const diff = targetIndex - currentPage;
|
||||
|
||||
const flipToTarget = (remaining: number) => {
|
||||
if (remaining === 0) return;
|
||||
|
||||
if (remaining > 0) {
|
||||
pageFlipAPI.flipNext();
|
||||
setTimeout(() => {
|
||||
setCurrentPage(prev => prev + 1);
|
||||
flipToTarget(remaining - 1);
|
||||
}, 300);
|
||||
} else {
|
||||
pageFlipAPI.flipPrev();
|
||||
setTimeout(() => {
|
||||
setCurrentPage(prev => prev - 1);
|
||||
flipToTarget(remaining + 1);
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
|
||||
flipToTarget(diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [currentPage, pages.length, goToNextPage, goToPrevPage]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-4 md:gap-6 w-full h-full" dir="rtl">
|
||||
{/* نمایش کتاب */}
|
||||
@@ -78,39 +154,39 @@ const BookViewer: FC<BookViewerProps> = ({ pages }) => {
|
||||
}}
|
||||
/>
|
||||
<div style={{ overflow: 'hidden', isolation: 'isolate' }}>
|
||||
<HTMLFlipBook
|
||||
ref={bookRef}
|
||||
width={397}
|
||||
height={561}
|
||||
size="fixed"
|
||||
minWidth={397}
|
||||
minHeight={561}
|
||||
maxWidth={397}
|
||||
maxHeight={561}
|
||||
drawShadow={true}
|
||||
flippingTime={800}
|
||||
usePortrait={false}
|
||||
startPage={0}
|
||||
autoSize={false}
|
||||
maxShadowOpacity={0.5}
|
||||
showCover={true}
|
||||
mobileScrollSupport={true}
|
||||
clickEventForward={true}
|
||||
useMouseEvents={true}
|
||||
swipeDistance={30}
|
||||
startZIndex={1}
|
||||
showPageCorners={true}
|
||||
disableFlipByClick={false}
|
||||
className="flipbook-container mx-auto"
|
||||
style={{
|
||||
direction: 'rtl',
|
||||
}}
|
||||
onFlip={handlePageFlip}
|
||||
>
|
||||
<HTMLFlipBook
|
||||
ref={bookRef}
|
||||
width={397}
|
||||
height={561}
|
||||
size="fixed"
|
||||
minWidth={397}
|
||||
minHeight={561}
|
||||
maxWidth={397}
|
||||
maxHeight={561}
|
||||
drawShadow={true}
|
||||
flippingTime={800}
|
||||
usePortrait={false}
|
||||
startPage={0}
|
||||
autoSize={false}
|
||||
maxShadowOpacity={0.5}
|
||||
showCover={true}
|
||||
mobileScrollSupport={true}
|
||||
clickEventForward={true}
|
||||
useMouseEvents={true}
|
||||
swipeDistance={30}
|
||||
startZIndex={1}
|
||||
showPageCorners={true}
|
||||
disableFlipByClick={true}
|
||||
className="flipbook-container mx-auto"
|
||||
style={{
|
||||
direction: 'rtl',
|
||||
}}
|
||||
onFlip={handlePageFlip}
|
||||
>
|
||||
{pages.map((page) => (
|
||||
<BookPage key={page.id} page={page} scale={0.5} />
|
||||
<BookPage key={page.id} page={page} scale={0.5} onLinkClick={handleLinkClick} />
|
||||
))}
|
||||
</HTMLFlipBook>
|
||||
</HTMLFlipBook>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user