mirror of
https://github.com/ClipFusion-org/clipfusion.git
synced 2025-08-08 00:14:20 +00:00
finally swipe to delete behaves like ios one
This commit is contained in:
parent
824a12b991
commit
27860244e5
@ -267,7 +267,10 @@ const ProjectDropdown = ({
|
|||||||
<div className="flex flex-row items-center w-[95%]">
|
<div className="flex flex-row items-center w-[95%]">
|
||||||
<SheetTitle className="font-semibold line-clamp-1">{project.title}</SheetTitle>
|
<SheetTitle className="font-semibold line-clamp-1">{project.title}</SheetTitle>
|
||||||
<SheetClose asChild>
|
<SheetClose asChild>
|
||||||
<Button variant="ghost" onClick={() => setRenameDialogOpen(true)}>
|
<Button variant="ghost" onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setRenameDialogOpen(true);
|
||||||
|
}}>
|
||||||
<PencilIcon /><span className="sr-only">Rename</span>
|
<PencilIcon /><span className="sr-only">Rename</span>
|
||||||
</Button>
|
</Button>
|
||||||
</SheetClose>
|
</SheetClose>
|
||||||
@ -463,11 +466,7 @@ const ProjectContainer = ({
|
|||||||
</SwipeToDelete>
|
</SwipeToDelete>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-[100% + 5 * var(--spacing)] -mx-5 overflow-hidden">
|
projectComponent
|
||||||
<div ref={containerRef} className="w-full bg-background px-5 py-2">
|
|
||||||
{projectComponent}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,12 +73,6 @@ main {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-scroll {
|
|
||||||
overflow: hidden;
|
|
||||||
height: 100%; /* Optional, but often recommended for full-page scroll prevention */
|
|
||||||
touch-action: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark body {
|
.dark body {
|
||||||
background-color: var(--color-background);
|
background-color: var(--color-background);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ const SwipeToDelete: FC<SwipeToDeleteProps> = ({
|
|||||||
deleteText = 'Delete',
|
deleteText = 'Delete',
|
||||||
fadeOnDeletion = true,
|
fadeOnDeletion = true,
|
||||||
useBoldDeleteFont = true,
|
useBoldDeleteFont = true,
|
||||||
threshold = 70
|
threshold = 75
|
||||||
}) => {
|
}) => {
|
||||||
const container = useRef<HTMLDivElement>(null);
|
const container = useRef<HTMLDivElement>(null);
|
||||||
const content = useRef<HTMLDivElement>(null);
|
const content = useRef<HTMLDivElement>(null);
|
||||||
@ -82,17 +82,21 @@ const SwipeToDelete: FC<SwipeToDeleteProps> = ({
|
|||||||
lastXRef.current = pageX;
|
lastXRef.current = pageX;
|
||||||
lastYRef.current = pageY;
|
lastYRef.current = pageY;
|
||||||
|
|
||||||
|
|
||||||
const raw = pageX - startX;
|
const raw = pageX - startX;
|
||||||
let x = dragX < 0 ? rubber(raw) : rubber(raw, width * 0.1);
|
let x = dragX < 0 ? rubber(raw) : rubber(raw, width * 0.1);
|
||||||
if ((Math.abs(dragX) === 0 ? Math.abs(vY) < window.innerHeight * 0.05 : true)) {
|
if ((Math.abs(dragX) === 0 ? Math.abs(vY) < window.innerHeight * 0.05 && Math.abs(vX) > Math.abs(vY) : true)) {
|
||||||
if (x < 0) setAllowOverscroll(true);
|
if (x < 0) setAllowOverscroll(true);
|
||||||
if (x <= 0 || (allowOverscroll && x >= 0)) setDragX(x);
|
if (x <= 0 || (allowOverscroll && x >= 0)) {
|
||||||
|
setDragX(x);
|
||||||
|
document.body.classList.add('no-scroll');
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
setDragX(0);
|
setDragX(0);
|
||||||
setAllowOverscroll(false);
|
setAllowOverscroll(false);
|
||||||
|
document.body.classList.remove('no-scroll');
|
||||||
}
|
}
|
||||||
if (Math.abs(vY) < 20) document.body.classList.add('no-scroll');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
@ -110,19 +114,16 @@ const SwipeToDelete: FC<SwipeToDeleteProps> = ({
|
|||||||
if (!dragging) return;
|
if (!dragging) return;
|
||||||
setDragging(false);
|
setDragging(false);
|
||||||
|
|
||||||
const shouldDelete =
|
const shouldDelete = isSticky || velocity < -1000;
|
||||||
isSticky ||
|
|
||||||
velocity < -1000;
|
|
||||||
setAllowOverscroll(false);
|
setAllowOverscroll(false);
|
||||||
document.body.classList.remove('no-scroll');
|
document.body.classList.remove('no-scroll');
|
||||||
if (Math.abs(velocityY) > window.innerHeight * 0.05) {
|
if (Math.abs(velocityY) > window.innerHeight * 0.05 && Math.abs(dragX) < 20) {
|
||||||
setDragX(0);
|
|
||||||
setDragX(0);
|
setDragX(0);
|
||||||
if (transparencyTimeout) {
|
if (transparencyTimeout) {
|
||||||
clearTimeout(transparencyTimeout);
|
clearTimeout(transparencyTimeout);
|
||||||
}
|
}
|
||||||
setForceTransparentBackground(true);
|
setForceTransparentBackground(true);
|
||||||
transparencyTimeout = setTimeout(() => setForceTransparentBackground(false), 150);
|
transparencyTimeout = setTimeout(() => setForceTransparentBackground(false), 200);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!shouldDelete) {
|
if (!shouldDelete) {
|
||||||
@ -130,14 +131,18 @@ const SwipeToDelete: FC<SwipeToDeleteProps> = ({
|
|||||||
text.current?.classList.add('ios-ease');
|
text.current?.classList.add('ios-ease');
|
||||||
const textWidth = text.current ? text.current.getBoundingClientRect().width : 0;
|
const textWidth = text.current ? text.current.getBoundingClientRect().width : 0;
|
||||||
if (((velocity < 0 && Math.abs(velocity) > 10) || dragX < -textWidth * 1.5 && velocity > 0) && text.current) {
|
if (((velocity < 0 && Math.abs(velocity) > 10) || dragX < -textWidth * 1.5 && velocity > 0) && text.current) {
|
||||||
setDragX(-textWidth * 1.5);
|
if (velocity < 0) {
|
||||||
} else if (allowOverscroll && dragX > 0) {
|
setDragX(-textWidth * 1.5);
|
||||||
|
} else {
|
||||||
|
setDragX(0);
|
||||||
|
}
|
||||||
|
} else if (allowOverscroll && dragX > 0 && velocity > 0) {
|
||||||
setDragX(0);
|
setDragX(0);
|
||||||
if (transparencyTimeout) {
|
if (transparencyTimeout) {
|
||||||
clearTimeout(transparencyTimeout);
|
clearTimeout(transparencyTimeout);
|
||||||
}
|
}
|
||||||
setForceTransparentBackground(true);
|
setForceTransparentBackground(true);
|
||||||
transparencyTimeout = setTimeout(() => setForceTransparentBackground(false), 150);
|
transparencyTimeout = setTimeout(() => setForceTransparentBackground(false), 200);
|
||||||
} else setDragX(0);
|
} else setDragX(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -217,7 +222,7 @@ const SwipeToDelete: FC<SwipeToDeleteProps> = ({
|
|||||||
|
|
||||||
const deleteTransform = isCollapsing
|
const deleteTransform = isCollapsing
|
||||||
? `translateX(calc(${dragX}px + 5rem))`
|
? `translateX(calc(${dragX}px + 5rem))`
|
||||||
: (isSticky ? `translateX(calc(${dragX}px + 5rem))` : `translateX(max(0rem, calc(${dragX}px + 5rem)))`);
|
: (isSticky ? `translateX(calc(${dragX}px + 5rem))` : `translateX(max(0rem + ${dragX * 0.07}px, calc(${dragX}px + 5rem)))`);
|
||||||
|
|
||||||
const opacityTransparent = fadeOnDeletion ? 0 : 1;
|
const opacityTransparent = fadeOnDeletion ? 0 : 1;
|
||||||
const backgroundTransparent = opacityTransparent == 0 ? 'transparent' : backgroundClass;
|
const backgroundTransparent = opacityTransparent == 0 ? 'transparent' : backgroundClass;
|
||||||
@ -255,7 +260,8 @@ const SwipeToDelete: FC<SwipeToDeleteProps> = ({
|
|||||||
marginTop: '1px',
|
marginTop: '1px',
|
||||||
marginBottom: '1px',
|
marginBottom: '1px',
|
||||||
paddingRight: '1rem',
|
paddingRight: '1rem',
|
||||||
transition: dragX > 1 ? '' : 'background 300ms'
|
transition: dragX > 1 ? '' : 'background 300ms',
|
||||||
|
willChange: 'background'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button style={{
|
<button style={{
|
||||||
@ -264,7 +270,8 @@ const SwipeToDelete: FC<SwipeToDeleteProps> = ({
|
|||||||
color: 'white',
|
color: 'white',
|
||||||
fontWeight: useBoldDeleteFont ? 600 : '',
|
fontWeight: useBoldDeleteFont ? 600 : '',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
opacity: isCollapsing ? opacityTransparent : 1
|
opacity: isCollapsing ? opacityTransparent : 1,
|
||||||
|
willChange: `transform, opacity`
|
||||||
}} onClick={handleDelete} ref={text}>
|
}} onClick={handleDelete} ref={text}>
|
||||||
{deleteText}
|
{deleteText}
|
||||||
</button>
|
</button>
|
||||||
|
@ -8,7 +8,10 @@
|
|||||||
touch-action: none;
|
touch-action: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.font-sharpen {
|
.no-scroll {
|
||||||
-webkit-transform: translateZ(0);
|
overflow: hidden;
|
||||||
transform: translateZ(0);
|
height: 100%;
|
||||||
|
/* Optional, but often recommended for full-page scroll prevention */
|
||||||
|
touch-action: none;
|
||||||
|
overscroll-behavior: none;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user