diff --git a/apps/desktop2/public/404.jpg b/apps/desktop2/public/404.jpg index 7485a5e8..c6859af2 100644 Binary files a/apps/desktop2/public/404.jpg and b/apps/desktop2/public/404.jpg differ diff --git a/apps/desktop2/src/components/note/preview/images.tsx b/apps/desktop2/src/components/note/preview/images.tsx index 401b0ae1..9b657bf3 100644 --- a/apps/desktop2/src/components/note/preview/images.tsx +++ b/apps/desktop2/src/components/note/preview/images.tsx @@ -1,23 +1,79 @@ -import { Carousel, CarouselItem } from "@lume/ui"; +import { ArrowLeftIcon, ArrowRightIcon } from "@lume/icons"; +import { Spinner } from "@lume/ui"; +import { cn } from "@lume/utils"; import { useRouteContext } from "@tanstack/react-router"; import { open } from "@tauri-apps/plugin-shell"; -import { useMemo } from "react"; +import useEmblaCarousel from "embla-carousel-react"; +import { useCallback, useEffect, useMemo, useState } from "react"; export function Images({ urls }: { urls: string[] }) { const { settings } = useRouteContext({ strict: false }); + const [slidesInView, setSlidesInView] = useState([]); + const [emblaRef, emblaApi] = useEmblaCarousel({ + dragFree: true, + align: "start", + watchSlides: false, + }); + const imageUrls = useMemo(() => { if (settings.image_resize_service.length) { - const newUrls = urls.map( - (url) => - `${settings.image_resize_service}?url=${url}&ll&af&default=1&n=-1`, - ); + let newUrls: string[]; + + if (urls.length === 1) { + newUrls = urls.map( + (url) => + `${settings.image_resize_service}?url=${url}&ll&af&default=1&n=-1`, + ); + } else { + newUrls = urls.map( + (url) => + `${settings.image_resize_service}?url=${url}&w=480&h=640&ll&af&default=1&n=-1`, + ); + } + return newUrls; } else { return urls; } }, [settings.image_resize_service]); + const scrollPrev = useCallback(() => { + if (emblaApi) emblaApi.scrollPrev(); + }, [emblaApi]); + + const scrollNext = useCallback(() => { + if (emblaApi) emblaApi.scrollNext(); + }, [emblaApi]); + + const updateSlidesInView = useCallback((emblaApi) => { + setSlidesInView((slidesInView) => { + if (slidesInView.length === emblaApi.slideNodes().length) { + emblaApi.off("slidesInView", updateSlidesInView); + } + + const inView = emblaApi + .slidesInView() + .filter((index) => !slidesInView.includes(index)); + + return slidesInView.concat(inView); + }); + }, []); + + useEffect(() => { + if (emblaApi && urls.length > 1) { + updateSlidesInView(emblaApi); + + emblaApi.on("slidesInView", updateSlidesInView); + emblaApi.on("reInit", updateSlidesInView); + } + + return () => { + emblaApi?.off("slidesInView", updateSlidesInView); + emblaApi?.off("reInit", updateSlidesInView); + }; + }, [emblaApi, updateSlidesInView]); + if (urls.length === 1) { return (