diff --git a/lama_cleaner/app/package.json b/lama_cleaner/app/package.json index eaf9957..dd83c4f 100644 --- a/lama_cleaner/app/package.json +++ b/lama_cleaner/app/package.json @@ -5,11 +5,14 @@ "proxy": "http://localhost:8080", "dependencies": { "@heroicons/react": "^2.0.0", + "@radix-ui/colors": "^0.1.8", "@radix-ui/react-dialog": "0.1.8-rc.25", "@radix-ui/react-icons": "^1.1.1", "@radix-ui/react-popover": "^1.0.0", + "@radix-ui/react-scroll-area": "^1.0.2", "@radix-ui/react-select": "0.1.2-rc.27", "@radix-ui/react-switch": "^0.1.5", + "@radix-ui/react-tabs": "^1.0.1", "@radix-ui/react-toast": "^0.1.1", "@radix-ui/react-tooltip": "^0.1.7", "@testing-library/jest-dom": "^5.14.1", diff --git a/lama_cleaner/app/src/components/FileManager/FileManager.scss b/lama_cleaner/app/src/components/FileManager/FileManager.scss index e530eb6..4353ae7 100644 --- a/lama_cleaner/app/src/components/FileManager/FileManager.scss +++ b/lama_cleaner/app/src/components/FileManager/FileManager.scss @@ -1,14 +1,13 @@ +@import '@radix-ui/colors/blackA.css'; +@import '@radix-ui/colors/mauve.css'; +@import '@radix-ui/colors/violet.css'; + .file-manager-modal { color: var(--text-color); height: 90%; width: 80%; } -.file-manager { - overflow: auto; - border-radius: 8px; -} - .react-photo-album.react-photo-album--columns { height: 80vh; } @@ -22,6 +21,64 @@ &:hover { border: 1px solid var(--border-color); - transform: scale(1.01); + transform: scale(1.03); } } + +.ScrollAreaRoot { + border-radius: 4px; + overflow: hidden; + // box-shadow: 0 2px 10px var(--blackA7); + --scrollbar-size: 10px; +} + +.ScrollAreaViewport { + width: 100%; + height: 100%; + border-radius: inherit; +} + +.ScrollAreaScrollbar { + display: flex; + /* ensures no selection */ + user-select: none; + /* disable browser handling of all panning and zooming gestures on touch devices */ + touch-action: none; + padding: 2px; + // background: var(--blackA6); + transition: background 160ms ease-out; +} + +.ScrollAreaScrollbar:hover { + background: var(--blackA8); +} +.ScrollAreaScrollbar[data-orientation='vertical'] { + width: var(--scrollbar-size); +} +.ScrollAreaScrollbar[data-orientation='horizontal'] { + flex-direction: column; + height: var(--scrollbar-size); +} + +.ScrollAreaThumb { + flex: 1; + background: var(--mauve10); + border-radius: var(--scrollbar-size); + position: relative; +} +/* increase target size for touch devices https://www.w3.org/WAI/WCAG21/Understanding/target-size.html */ +.ScrollAreaThumb::before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 100%; + height: 100%; + min-width: 44px; + min-height: 44px; +} + +.ScrollAreaCorner { + background: var(--blackA8); +} diff --git a/lama_cleaner/app/src/components/FileManager/FileManager.tsx b/lama_cleaner/app/src/components/FileManager/FileManager.tsx index 40593a0..2d820f0 100644 --- a/lama_cleaner/app/src/components/FileManager/FileManager.tsx +++ b/lama_cleaner/app/src/components/FileManager/FileManager.tsx @@ -1,6 +1,15 @@ -import React, { ReactNode, useEffect, useMemo, useState } from 'react' +import React, { + SyntheticEvent, + useEffect, + useMemo, + useState, + useCallback, + useRef, +} from 'react' import PhotoAlbum, { RenderPhoto } from 'react-photo-album' +import * as ScrollArea from '@radix-ui/react-scroll-area' import Modal from '../shared/Modal' +import Button from '../shared/Button' interface Photo { src: string @@ -36,12 +45,35 @@ const renderPhoto: RenderPhoto = ({ interface Props { show: boolean onClose: () => void - onPhotoClick: (filename: string) => void + onPhotoClick(filename: string): void + photoWidth: number } export default function FileManager(props: Props) { - const { show, onClose, onPhotoClick } = props + const { show, onClose, onPhotoClick, photoWidth } = props const [filenames, setFileNames] = useState([]) + const [scrollTop, setScrollTop] = useState(0) + const [closeScrollTop, setCloseScrollTop] = useState(0) + + useEffect(() => { + if (!show) { + setCloseScrollTop(scrollTop) + } + }, [show, scrollTop]) + + const onRefChange = useCallback( + (node: HTMLDivElement) => { + if (node !== null) { + if (show) { + setTimeout(() => { + // TODO: without timeout, scrollTo not work, why? + node.scrollTo({ top: closeScrollTop, left: 0 }) + }, 100) + } + } + }, + [show, closeScrollTop] + ) const onClick = ({ index }: { index: number }) => { onPhotoClick(filenames[index].name) @@ -59,9 +91,13 @@ export default function FileManager(props: Props) { fetchData() }, []) + const onScroll = (event: SyntheticEvent) => { + setScrollTop(event.currentTarget.scrollTop) + } + const photos = useMemo(() => { return filenames.map((filename: Filename) => { - const width = 256 + const width = photoWidth const height = filename.height * (width / filename.width) const src = `/media_thumbnail/${filename.name}?width=${width}&height=${height}` return { src, height, width } @@ -71,20 +107,39 @@ export default function FileManager(props: Props) { return ( -
- -
+ + + + + + + + + + + +
) } diff --git a/lama_cleaner/app/src/components/Header/Header.tsx b/lama_cleaner/app/src/components/Header/Header.tsx index 56807e5..dfb2ab6 100644 --- a/lama_cleaner/app/src/components/Header/Header.tsx +++ b/lama_cleaner/app/src/components/Header/Header.tsx @@ -4,6 +4,7 @@ import React, { useState } from 'react' import { useRecoilState, useRecoilValue } from 'recoil' import * as PopoverPrimitive from '@radix-ui/react-popover' import { + enableFileManagerState, fileState, isInpaintingState, isSDState, @@ -33,14 +34,17 @@ const Header = () => { const [openMaskPopover, setOpenMaskPopover] = useState(false) const [showFileManager, setShowFileManager] = useRecoilState(showFileManagerState) + const enableFileManager = useRecoilValue(enableFileManagerState) useHotKey( 'f', () => { - setShowFileManager(!showFileManager) + if (enableFileManager) { + setShowFileManager(!showFileManager) + } }, {}, - [showFileManager] + [showFileManager, enableFileManager] ) const renderHeader = () => { @@ -54,15 +58,19 @@ const Header = () => { gap: 8, }} > -