From 7fbab934fff39cee52eed8884def4534468dd05c Mon Sep 17 00:00:00 2001 From: corgifist Date: Mon, 4 Aug 2025 22:46:43 +0300 Subject: [PATCH] added chrome specific blurry text fix --- src/app/(dashboard)/page.tsx | 22 ++++++++---- src/app/(dashboard)/settings/page.tsx | 21 +++++++---- .../swipe-to-delete/SwipeToDelete.tsx | 26 +++++++++----- src/hooks/use-browser-engine.ts | 36 +++++++++++++++++++ src/hooks/use-user-agent.ts | 15 ++++++++ 5 files changed, 99 insertions(+), 21 deletions(-) create mode 100644 src/hooks/use-browser-engine.ts create mode 100644 src/hooks/use-user-agent.ts diff --git a/src/app/(dashboard)/page.tsx b/src/app/(dashboard)/page.tsx index 024b40a..767e670 100644 --- a/src/app/(dashboard)/page.tsx +++ b/src/app/(dashboard)/page.tsx @@ -160,7 +160,7 @@ const RenameProjectDialog = ({ project }: { project: Project }) => {
- + @@ -416,6 +416,7 @@ const ProjectContainer = ({ setContainer(node); }; const isMobile = useIsMobile(); + const swipeToDelete = useIsMobile(640); const date = new Date(project.editDate); @@ -432,7 +433,7 @@ const ProjectContainer = ({ const LinkComponent = selecting ? "div" : Link; const projectComponent = ( - +
@@ -457,16 +458,23 @@ const ProjectContainer = ({ ); - return isMobile && !selecting ? ( -
- deleteProject(project.uuid)}> + + return isMobile && !selecting && swipeToDelete ? ( +
+ deleteProject(project.uuid)}>
{projectComponent}
) : ( - projectComponent + swipeToDelete ? ( +
+
+ {projectComponent} +
+
+ ) : projectComponent ); }; @@ -481,7 +489,7 @@ export default function Home(): ReactNode { const [showDeleteSelectedAlert, setShowDeleteSelectedAlert] = useState(false); const projects = useLiveQuery(async () => ( - db.projects.toArray() + await db.projects.toArray() )); const filteredProjects = projects && ( diff --git a/src/app/(dashboard)/settings/page.tsx b/src/app/(dashboard)/settings/page.tsx index 081fdb6..bd82b30 100644 --- a/src/app/(dashboard)/settings/page.tsx +++ b/src/app/(dashboard)/settings/page.tsx @@ -1,6 +1,6 @@ "use client"; import { ChartPieIcon, ChevronRightIcon } from "lucide-react"; -import { ReactNode, } from "react"; +import { ReactNode, useState, } from "react"; import StaticSidebarTrigger from "@/components/static-sidebar-trigger"; import ScrollFadingTitle from "@/components/scroll-fading-title"; import SidebarTriggerAdjustable from "@/components/sidebar-trigger-adjustable"; @@ -10,11 +10,17 @@ import AscendingCard from "@/components/ascending-card"; import Link from "next/link"; import WideContainer from "@/components/wide-container"; 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 { + const [showUserAgent, setShowUserAgent] = useState(false); const isMobile = useIsMobile(); const shortBuildId = useIsMobile(1024); + const browserEngine = useBrowserEngine(); + const userAgent = useUserAgent(); + const buildID = getBuildID(); return ( @@ -49,11 +55,14 @@ export default function Settings(): ReactNode { - - {getVersion()} ({shortBuildId ? buildID?.slice(0, 7) : buildID}) - +
+ + {getVersion()} ({shortBuildId ? buildID?.slice(0, 7) : buildID}) + +

setShowUserAgent(!showUserAgent)}>{showUserAgent ? userAgent : `running on ${browserEngine}`}

+
diff --git a/src/components/swipe-to-delete/SwipeToDelete.tsx b/src/components/swipe-to-delete/SwipeToDelete.tsx index 8b2673e..bb77f88 100644 --- a/src/components/swipe-to-delete/SwipeToDelete.tsx +++ b/src/components/swipe-to-delete/SwipeToDelete.tsx @@ -1,5 +1,6 @@ -'use client' -import React, { useRef, useState, useEffect, FC, ReactNode } from 'react' +'use client'; +import useBrowserEngine from '@/hooks/use-browser-engine'; +import React, { useRef, useState, useEffect, FC, ReactNode, CSSProperties } from 'react' type SwipeToDeleteProps = { children: ReactNode; @@ -26,6 +27,15 @@ const SwipeToDelete: FC = ({ const content = useRef(null); const text = useRef(null); + const browser = useBrowserEngine(); + + const applyBlurFix = (style: CSSProperties) => { + if (browser == 'Blink') { + style.willChange = undefined; + } + return style; + }; + // drag state const [dragX, setDragX] = useState(0); const [dragging, setDragging] = useState(false); @@ -85,18 +95,18 @@ const SwipeToDelete: FC = ({ const raw = pageX - startX; 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 (x < 0) setAllowOverscroll(true); + if (x < -1) setAllowOverscroll(true); if (x <= 0 || (allowOverscroll && x >= 0)) { setDragX(x); document.body.classList.add('no-scroll'); } - + } else { setDragX(0); setAllowOverscroll(false); document.body.classList.remove('no-scroll'); } - + }; const handleDelete = () => { @@ -131,7 +141,7 @@ const SwipeToDelete: FC = ({ text.current?.classList.add('ios-ease'); 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) { + if (velocity < -10) { setDragX(-textWidth * 1.5); } else { setDragX(0); @@ -281,7 +291,7 @@ const SwipeToDelete: FC = ({
= ({ ? '' : 'transform 300ms cubic-bezier(0.24, 1.04, 0.56, 1)', willChange: 'transform' - }} + })} > {children}
diff --git a/src/hooks/use-browser-engine.ts b/src/hooks/use-browser-engine.ts new file mode 100644 index 0000000..0189f2d --- /dev/null +++ b/src/hooks/use-browser-engine.ts @@ -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('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; \ No newline at end of file diff --git a/src/hooks/use-user-agent.ts b/src/hooks/use-user-agent.ts new file mode 100644 index 0000000..61e51f8 --- /dev/null +++ b/src/hooks/use-user-agent.ts @@ -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(); + + useEffect(() => { + setUserAgent(navigator.userAgent); + }, []); + + return userAgent; +}; + +export default useUserAgent; \ No newline at end of file