forked from akai/readest
ui: fix layout in mobile platforms (#371)
This commit is contained in:
@@ -138,7 +138,7 @@ const Bookshelf: React.FC<BookshelfProps> = ({
|
||||
|
||||
return (
|
||||
<div className='bookshelf'>
|
||||
<div className='grid flex-1 grid-cols-3 gap-0 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8'>
|
||||
<div className='transform-wrapper grid flex-1 grid-cols-3 gap-0 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8'>
|
||||
{currentBookshelfItems.map((item, index) => (
|
||||
<BookshelfItem
|
||||
key={`library-item-${index}`}
|
||||
@@ -172,7 +172,7 @@ const Bookshelf: React.FC<BookshelfProps> = ({
|
||||
<Spinner loading />
|
||||
</div>
|
||||
)}
|
||||
<div className={clsx('action-bar-bottom z-[99] pb-[calc(env(safe-area-inset-bottom)+16px)]')}>
|
||||
<div className='fixed bottom-0 left-0 right-0 z-40 pb-[calc(env(safe-area-inset-bottom)+16px)]'>
|
||||
{isSelectMode && showSelectModeActions && (
|
||||
<div
|
||||
className={clsx(
|
||||
@@ -241,7 +241,7 @@ const Bookshelf: React.FC<BookshelfProps> = ({
|
||||
{showDeleteAlert && (
|
||||
<div
|
||||
className={clsx(
|
||||
'action-bar-bottom z-[100] flex justify-center',
|
||||
'fixed bottom-0 z-50 flex justify-center',
|
||||
'pb-[calc(env(safe-area-inset-bottom)+16px)]',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -133,7 +133,7 @@ const BookshelfItem: React.FC<BookshelfItemProps> = ({
|
||||
if (isSelectMode) {
|
||||
toggleSelection(group.id);
|
||||
} else {
|
||||
navigateToLibrary(router, `group=${group.id}`, { scroll: false });
|
||||
navigateToLibrary(router, `group=${group.id}`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -219,7 +219,6 @@ const BookshelfItem: React.FC<BookshelfItemProps> = ({
|
||||
)}
|
||||
style={{
|
||||
transition: 'transform 0.2s',
|
||||
touchAction: 'none',
|
||||
}}
|
||||
{...handlers}
|
||||
onContextMenu={(event) => handleItemContextMenu(item, event)}
|
||||
|
||||
@@ -35,7 +35,7 @@ const LibraryHeader: React.FC<LibraryHeaderProps> = ({
|
||||
const { isTrafficLightVisible } = useTrafficLight();
|
||||
const headerRef = useRef<HTMLDivElement>(null);
|
||||
const iconSize16 = useResponsiveSize(16);
|
||||
const iconSize22 = useResponsiveSize(22);
|
||||
const iconSize20 = useResponsiveSize(20);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
@@ -68,10 +68,10 @@ const LibraryHeader: React.FC<LibraryHeaderProps> = ({
|
||||
onClick={() => {
|
||||
navigateToLibrary(router);
|
||||
}}
|
||||
className='btn btn-ghost mr-4 h-7 min-h-7 w-7 p-0'
|
||||
className='ml-[-6px] mr-4 flex h-7 min-h-7 w-7 items-center p-0'
|
||||
>
|
||||
<div className='lg:tooltip lg:tooltip-bottom' data-tip={_('Go Back')}>
|
||||
<MdArrowBackIosNew size={iconSize22} />
|
||||
<MdArrowBackIosNew size={iconSize20} />
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -43,27 +43,21 @@ export const useLongPress = ({
|
||||
|
||||
const handlePointerDown = useCallback(
|
||||
(e: React.PointerEvent) => {
|
||||
if (e.pointerType === 'touch') {
|
||||
const target = e.target as HTMLElement;
|
||||
if (target instanceof Element) {
|
||||
target.setPointerCapture(e.pointerId);
|
||||
}
|
||||
}
|
||||
|
||||
if (e.pointerType === 'mouse' && e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
pointerId.current = e.pointerId;
|
||||
startPosRef.current = { x: e.clientX, y: e.clientY };
|
||||
isLongPressTriggered.current = false;
|
||||
setPressing(true);
|
||||
|
||||
timerRef.current = setTimeout(() => {
|
||||
isLongPressTriggered.current = true;
|
||||
onLongPress?.();
|
||||
setPressing(false);
|
||||
if (startPosRef.current) {
|
||||
isLongPressTriggered.current = true;
|
||||
onLongPress?.();
|
||||
setPressing(false);
|
||||
}
|
||||
}, threshold);
|
||||
},
|
||||
[onLongPress, threshold],
|
||||
@@ -71,17 +65,14 @@ export const useLongPress = ({
|
||||
|
||||
const handlePointerMove = useCallback(
|
||||
(e: React.PointerEvent) => {
|
||||
// Only handle moves for the same pointer that started the press
|
||||
if (e.pointerId !== pointerId.current) return;
|
||||
if (e.pointerId !== pointerId.current || !startPosRef.current) return;
|
||||
|
||||
if (startPosRef.current) {
|
||||
const deltaX = Math.abs(e.clientX - startPosRef.current.x);
|
||||
const deltaY = Math.abs(e.clientY - startPosRef.current.y);
|
||||
const deltaX = Math.abs(e.clientX - startPosRef.current.x);
|
||||
const deltaY = Math.abs(e.clientY - startPosRef.current.y);
|
||||
|
||||
if (deltaX > moveThreshold || deltaY > moveThreshold) {
|
||||
onCancel?.();
|
||||
reset();
|
||||
}
|
||||
if (deltaX > moveThreshold || deltaY > moveThreshold) {
|
||||
onCancel?.();
|
||||
reset();
|
||||
}
|
||||
},
|
||||
[moveThreshold, onCancel, reset],
|
||||
@@ -92,18 +83,22 @@ export const useLongPress = ({
|
||||
if (e.pointerId !== pointerId.current) return;
|
||||
|
||||
if (!isLongPressTriggered.current && startPosRef.current) {
|
||||
onTap?.();
|
||||
const deltaX = Math.abs(e.clientX - startPosRef.current.x);
|
||||
const deltaY = Math.abs(e.clientY - startPosRef.current.y);
|
||||
|
||||
if (deltaX <= moveThreshold && deltaY <= moveThreshold) {
|
||||
onTap?.();
|
||||
}
|
||||
}
|
||||
|
||||
reset();
|
||||
},
|
||||
[onTap, reset],
|
||||
[onTap, moveThreshold, reset],
|
||||
);
|
||||
|
||||
const handleCancel = useCallback(
|
||||
(e: React.PointerEvent) => {
|
||||
if (e.pointerId !== pointerId.current) return;
|
||||
|
||||
onCancel?.();
|
||||
reset();
|
||||
},
|
||||
@@ -111,7 +106,9 @@ export const useLongPress = ({
|
||||
);
|
||||
|
||||
const handleContextMenu = useCallback((e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
if (isLongPressTriggered.current) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -44,7 +44,10 @@ export const usePullToRefresh = (ref: React.RefObject<HTMLDivElement>, onTrigger
|
||||
removePullIndicator(parentEl);
|
||||
}
|
||||
|
||||
el.style.transform = `translateY(${appr(dy)}px)`;
|
||||
const wrapper = el.querySelector('.transform-wrapper') as HTMLElement;
|
||||
if (wrapper) {
|
||||
wrapper.style.transform = `translate3d(0, ${appr(dy)}px, 0)`;
|
||||
}
|
||||
}
|
||||
|
||||
function addPullIndicator(el: HTMLDivElement) {
|
||||
@@ -84,7 +87,10 @@ export const usePullToRefresh = (ref: React.RefObject<HTMLDivElement>, onTrigger
|
||||
const el = ref.current;
|
||||
if (!el) return;
|
||||
|
||||
el.style.transform = 'translateY(0)';
|
||||
const wrapper = el.querySelector('.transform-wrapper') as HTMLElement;
|
||||
if (wrapper) {
|
||||
wrapper.style.transform = 'translateY(0)';
|
||||
}
|
||||
removePullIndicator(el.parentNode as HTMLDivElement);
|
||||
|
||||
el.style.transition = 'transform 0.2s';
|
||||
|
||||
@@ -230,10 +230,3 @@ foliate-view {
|
||||
.pull-indicator.flip svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.action-bar-bottom {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user