mirror of
https://github.com/ClipFusion-org/clipfusion.git
synced 2025-08-08 00:14:20 +00:00
added chrome specific blurry text fix
This commit is contained in:
parent
27860244e5
commit
7fbab934ff
@ -416,6 +416,7 @@ const ProjectContainer = ({
|
|||||||
setContainer(node);
|
setContainer(node);
|
||||||
};
|
};
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
const swipeToDelete = useIsMobile(640);
|
||||||
|
|
||||||
const date = new Date(project.editDate);
|
const date = new Date(project.editDate);
|
||||||
|
|
||||||
@ -432,7 +433,7 @@ const ProjectContainer = ({
|
|||||||
const LinkComponent = selecting ? "div" : Link;
|
const LinkComponent = selecting ? "div" : Link;
|
||||||
|
|
||||||
const projectComponent = (
|
const projectComponent = (
|
||||||
<AspectRatio className="relative" data-selectable="true" ratio={16 / 9}>
|
<AspectRatio className="relative w-full h-auto" data-selectable="true" ratio={16 / 9}>
|
||||||
<AscendingCard className="absolute top-0 left-0 w-full h-full overflow-hidden p-0">
|
<AscendingCard className="absolute top-0 left-0 w-full h-full overflow-hidden p-0">
|
||||||
<LinkComponent href={`/editor/${project.uuid}`} className="absolute top-0 left-0 w-full h-full overflow-hidden">
|
<LinkComponent href={`/editor/${project.uuid}`} className="absolute top-0 left-0 w-full h-full overflow-hidden">
|
||||||
<div className="relative w-full h-full rounded-lg overflow-hidden" data-selectable="true" onClick={handleCheck}>
|
<div className="relative w-full h-full rounded-lg overflow-hidden" data-selectable="true" onClick={handleCheck}>
|
||||||
@ -457,16 +458,23 @@ const ProjectContainer = ({
|
|||||||
</AspectRatio>
|
</AspectRatio>
|
||||||
);
|
);
|
||||||
|
|
||||||
return isMobile && !selecting ? (
|
|
||||||
<div className="w-[100% + 5 * var(--spacing)] -mx-5 overflow-hidden">
|
return isMobile && !selecting && swipeToDelete ? (
|
||||||
<SwipeToDelete height={container ? Math.floor(container.getBoundingClientRect().height) : 210} onDelete={() => deleteProject(project.uuid)}>
|
<div className="w-[100% + 5 * var(--spacing)] -mx-5 -my-[2px] overflow-hidden">
|
||||||
|
<SwipeToDelete height={container ? container.getBoundingClientRect().height : 210} onDelete={() => deleteProject(project.uuid)}>
|
||||||
<div ref={containerRef} className="w-full bg-background px-5 py-2">
|
<div ref={containerRef} className="w-full bg-background px-5 py-2">
|
||||||
{projectComponent}
|
{projectComponent}
|
||||||
</div>
|
</div>
|
||||||
</SwipeToDelete>
|
</SwipeToDelete>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
projectComponent
|
swipeToDelete ? (
|
||||||
|
<div className="w-[100% + 5 * var(--spacing)] -mx-5 -my-[2px] overflow-hidden">
|
||||||
|
<div ref={containerRef} className="w-full bg-background px-5 py-2">
|
||||||
|
{projectComponent}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : projectComponent
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -481,7 +489,7 @@ export default function Home(): ReactNode {
|
|||||||
const [showDeleteSelectedAlert, setShowDeleteSelectedAlert] = useState(false);
|
const [showDeleteSelectedAlert, setShowDeleteSelectedAlert] = useState(false);
|
||||||
|
|
||||||
const projects = useLiveQuery(async () => (
|
const projects = useLiveQuery(async () => (
|
||||||
db.projects.toArray()
|
await db.projects.toArray()
|
||||||
));
|
));
|
||||||
|
|
||||||
const filteredProjects = projects && (
|
const filteredProjects = projects && (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { ChartPieIcon, ChevronRightIcon } from "lucide-react";
|
import { ChartPieIcon, ChevronRightIcon } from "lucide-react";
|
||||||
import { ReactNode, } from "react";
|
import { ReactNode, useState, } from "react";
|
||||||
import StaticSidebarTrigger from "@/components/static-sidebar-trigger";
|
import StaticSidebarTrigger from "@/components/static-sidebar-trigger";
|
||||||
import ScrollFadingTitle from "@/components/scroll-fading-title";
|
import ScrollFadingTitle from "@/components/scroll-fading-title";
|
||||||
import SidebarTriggerAdjustable from "@/components/sidebar-trigger-adjustable";
|
import SidebarTriggerAdjustable from "@/components/sidebar-trigger-adjustable";
|
||||||
@ -10,11 +10,17 @@ import AscendingCard from "@/components/ascending-card";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import WideContainer from "@/components/wide-container";
|
import WideContainer from "@/components/wide-container";
|
||||||
import { getBuildID, getVersion } from "@/lib/build";
|
import { getBuildID, getVersion } from "@/lib/build";
|
||||||
|
import useBrowserEngine from "@/hooks/use-browser-engine";
|
||||||
|
import useUserAgent from "@/hooks/use-user-agent";
|
||||||
|
|
||||||
|
|
||||||
export default function Settings(): ReactNode {
|
export default function Settings(): ReactNode {
|
||||||
|
const [showUserAgent, setShowUserAgent] = useState(false);
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
const shortBuildId = useIsMobile(1024);
|
const shortBuildId = useIsMobile(1024);
|
||||||
|
const browserEngine = useBrowserEngine();
|
||||||
|
const userAgent = useUserAgent();
|
||||||
|
|
||||||
const buildID = getBuildID();
|
const buildID = getBuildID();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -49,11 +55,14 @@ export default function Settings(): ReactNode {
|
|||||||
<ChevronRightIcon />
|
<ChevronRightIcon />
|
||||||
</AscendingCard>
|
</AscendingCard>
|
||||||
</Link>
|
</Link>
|
||||||
<Link className="text-sm text-muted-foreground flex justify-center" target="_blank" href={
|
<div className="flex flex-col justify-center items-center text-center w-full text-sm text-muted-foreground">
|
||||||
|
<Link className="" target="_blank" href={
|
||||||
`https://github.com/ClipFusion-org/clipfusion/commit/${buildID}`
|
`https://github.com/ClipFusion-org/clipfusion/commit/${buildID}`
|
||||||
}>
|
}>
|
||||||
{getVersion()} ({shortBuildId ? buildID?.slice(0, 7) : buildID})
|
{getVersion()} ({shortBuildId ? buildID?.slice(0, 7) : buildID})
|
||||||
</Link>
|
</Link>
|
||||||
|
<p onClick={() => setShowUserAgent(!showUserAgent)}>{showUserAgent ? userAgent : `running on ${browserEngine}`}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</WideContainer>
|
</WideContainer>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
'use client'
|
'use client';
|
||||||
import React, { useRef, useState, useEffect, FC, ReactNode } from 'react'
|
import useBrowserEngine from '@/hooks/use-browser-engine';
|
||||||
|
import React, { useRef, useState, useEffect, FC, ReactNode, CSSProperties } from 'react'
|
||||||
|
|
||||||
type SwipeToDeleteProps = {
|
type SwipeToDeleteProps = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
@ -26,6 +27,15 @@ const SwipeToDelete: FC<SwipeToDeleteProps> = ({
|
|||||||
const content = useRef<HTMLDivElement>(null);
|
const content = useRef<HTMLDivElement>(null);
|
||||||
const text = useRef<HTMLButtonElement>(null);
|
const text = useRef<HTMLButtonElement>(null);
|
||||||
|
|
||||||
|
const browser = useBrowserEngine();
|
||||||
|
|
||||||
|
const applyBlurFix = (style: CSSProperties) => {
|
||||||
|
if (browser == 'Blink') {
|
||||||
|
style.willChange = undefined;
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
};
|
||||||
|
|
||||||
// drag state
|
// drag state
|
||||||
const [dragX, setDragX] = useState(0);
|
const [dragX, setDragX] = useState(0);
|
||||||
const [dragging, setDragging] = useState(false);
|
const [dragging, setDragging] = useState(false);
|
||||||
@ -85,7 +95,7 @@ const SwipeToDelete: FC<SwipeToDeleteProps> = ({
|
|||||||
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 && Math.abs(vX) > Math.abs(vY) : 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 < -1) setAllowOverscroll(true);
|
||||||
if (x <= 0 || (allowOverscroll && x >= 0)) {
|
if (x <= 0 || (allowOverscroll && x >= 0)) {
|
||||||
setDragX(x);
|
setDragX(x);
|
||||||
document.body.classList.add('no-scroll');
|
document.body.classList.add('no-scroll');
|
||||||
@ -131,7 +141,7 @@ 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) {
|
||||||
if (velocity < 0) {
|
if (velocity < -10) {
|
||||||
setDragX(-textWidth * 1.5);
|
setDragX(-textWidth * 1.5);
|
||||||
} else {
|
} else {
|
||||||
setDragX(0);
|
setDragX(0);
|
||||||
@ -281,7 +291,7 @@ const SwipeToDelete: FC<SwipeToDeleteProps> = ({
|
|||||||
<div
|
<div
|
||||||
ref={content}
|
ref={content}
|
||||||
className="ios-ease"
|
className="ios-ease"
|
||||||
style={{
|
style={applyBlurFix({
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
inset: 0,
|
inset: 0,
|
||||||
transform: `translateX(${Math.floor(dragX)}px)`,
|
transform: `translateX(${Math.floor(dragX)}px)`,
|
||||||
@ -289,7 +299,7 @@ const SwipeToDelete: FC<SwipeToDeleteProps> = ({
|
|||||||
? ''
|
? ''
|
||||||
: 'transform 300ms cubic-bezier(0.24, 1.04, 0.56, 1)',
|
: 'transform 300ms cubic-bezier(0.24, 1.04, 0.56, 1)',
|
||||||
willChange: 'transform'
|
willChange: 'transform'
|
||||||
}}
|
})}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
36
src/hooks/use-browser-engine.ts
Normal file
36
src/hooks/use-browser-engine.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
type Engine = 'Blink' | 'WebKit' | 'Gecko' | 'Trident' | 'Unknown';
|
||||||
|
|
||||||
|
// small hook for detecting browser's rendering engine (blink, webkit etc.)
|
||||||
|
// makes applying browser-specific workarounds easier
|
||||||
|
// for example you can use it to fix blurry text on chrome when using transform (css property)
|
||||||
|
|
||||||
|
const useBrowserEngine = (): Engine => {
|
||||||
|
const [engine, setEngine] = useState<Engine>('Unknown');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const ua = navigator.userAgent;
|
||||||
|
|
||||||
|
if (/Trident|MSIE/.test(ua)) {
|
||||||
|
setEngine('Trident');
|
||||||
|
} else if (/Firefox/.test(ua)) {
|
||||||
|
setEngine('Gecko');
|
||||||
|
} else if (/Edge/.test(ua) || (/Chrome/.test(ua) && /Safari/.test(ua) && !/OPR/.test(ua))) {
|
||||||
|
setEngine('Blink');
|
||||||
|
} else if (/Safari/.test(ua) && !/Chrome/.test(ua)) {
|
||||||
|
setEngine('WebKit');
|
||||||
|
} else if (/AppleWebKit/.test(ua)) {
|
||||||
|
// covers some Chrome-based UAs that don’t explicitly list Google Inc vendor
|
||||||
|
setEngine('Blink');
|
||||||
|
} else if (/Opera/.test(ua) || /OPR/.test(ua)) {
|
||||||
|
setEngine('Blink');
|
||||||
|
} else {
|
||||||
|
setEngine('Unknown');
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useBrowserEngine;
|
15
src/hooks/use-user-agent.ts
Normal file
15
src/hooks/use-user-agent.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
// making this a separate hook helps declutter the main codebase a little
|
||||||
|
|
||||||
|
const useUserAgent = (): string | undefined => {
|
||||||
|
const [userAgent, setUserAgent] = useState<string>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setUserAgent(navigator.userAgent);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return userAgent;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useUserAgent;
|
Loading…
Reference in New Issue
Block a user