diff --git a/components/system/Files/FileEntry/RenameBox.tsx b/components/system/Files/FileEntry/RenameBox.tsx index e67e15d5..67afe311 100644 --- a/components/system/Files/FileEntry/RenameBox.tsx +++ b/components/system/Files/FileEntry/RenameBox.tsx @@ -1,7 +1,9 @@ +import { getLineCount } from "components/system/Files/FileEntry/functions"; import { haltEvent } from "components/system/Files/FileManager/functions"; import StyledRenameBox from "components/system/Files/Views/StyledRenameBox"; import { extname } from "path"; -import { useEffect, useRef } from "react"; +import { useCallback, useEffect, useRef } from "react"; +import { useTheme } from "styled-components"; import { PREVENT_SCROLL } from "utils/constants"; type RenameBoxProps = { @@ -13,11 +15,31 @@ type RenameBoxProps = { const RenameBox = ({ name, path, renameFile }: RenameBoxProps): JSX.Element => { const inputRef = useRef(null); const saveRename = (): void => renameFile(path, inputRef.current?.value); + const { formats, sizes } = useTheme(); + const updateRows = useCallback( + (text: string): void => { + const lines = getLineCount( + text, + sizes.fileEntry.fontSize, + formats.systemFont, + sizes.fileEntry.renameWidth - sizes.fileEntry.renamePadding * 2 + ); + + inputRef.current?.setAttribute("rows", lines.toString()); + }, + [ + formats.systemFont, + sizes.fileEntry.fontSize, + sizes.fileEntry.renamePadding, + sizes.fileEntry.renameWidth, + ] + ); useEffect(() => { inputRef.current?.focus(PREVENT_SCROLL); inputRef.current?.setSelectionRange(0, name.length - extname(name).length); - }, [name]); + updateRows(name); + }, [name, updateRows]); return ( { onBlurCapture={saveRename} onClick={haltEvent} onKeyDown={({ key }) => key === "Enter" && saveRename()} - onKeyUp={haltEvent} + onKeyUp={(event) => { + if (event.target instanceof HTMLTextAreaElement) { + updateRows(event.target.value); + } + + haltEvent(event); + }} ref={inputRef} /> ); diff --git a/components/system/Files/FileEntry/functions.ts b/components/system/Files/FileEntry/functions.ts index e0e922ee..19ede4ca 100644 --- a/components/system/Files/FileEntry/functions.ts +++ b/components/system/Files/FileEntry/functions.ts @@ -176,3 +176,37 @@ export const filterSystemFiles = (directory: string) => (file: string): boolean => !SYSTEM_PATHS.has(join(directory, file)) && !SYSTEM_FILES.has(file); + +export const getLineCount = ( + text: string, + fontSize: string, + fontFamily: string, + maxWidth: number +): number => { + const canvas = document.createElement("canvas"); + const context = canvas.getContext("2d", { + alpha: false, + desynchronized: true, + }) as CanvasRenderingContext2D; + + context.font = `${fontSize} ${fontFamily}`; + + if (context.measureText(text).width > maxWidth) { + const lines = [""]; + + [...text].forEach((character) => { + const lineCount = lines.length - 1; + const lineText = `${lines[lineCount]}${character}`; + + if (context.measureText(lineText).width > maxWidth) { + lines.push(character); + } else { + lines[lineCount] = lineText; + } + }); + + return lines.length; + } + + return 1; +}; diff --git a/components/system/Files/FileManager/index.tsx b/components/system/Files/FileManager/index.tsx index 1a1f80d4..d4f53574 100644 --- a/components/system/Files/FileManager/index.tsx +++ b/components/system/Files/FileManager/index.tsx @@ -17,6 +17,7 @@ import { MOUNTABLE_EXTENSIONS, SHORTCUT_EXTENSION } from "utils/constants"; type FileManagerProps = { closing?: boolean; hideLoading?: boolean; + hideScrolling?: boolean; url: string; view: FileManagerViewNames; }; @@ -24,6 +25,7 @@ type FileManagerProps = { const FileManager = ({ closing, hideLoading, + hideScrolling, url, view, }: FileManagerProps): JSX.Element => { @@ -60,6 +62,7 @@ const FileManager = ({ ) : ( ` grid-template-rows: ${({ theme }) => `repeat(auto-fill, ${theme.sizes.fileManager.gridEntryHeight})`}; height: ${({ theme }) => `calc(100% - ${theme.sizes.taskbar.height})`}; + overflow: ${({ scrollable }) => (scrollable ? undefined : "hidden")}; padding: ${({ theme }) => theme.sizes.fileManager.padding}; pointer-events: ${({ selecting }) => (selecting ? "auto" : undefined)}; row-gap: ${({ theme }) => theme.sizes.fileManager.rowGap}; diff --git a/components/system/Files/Views/StyledRenameBox.ts b/components/system/Files/Views/StyledRenameBox.ts index 758f4b63..bece9d3f 100644 --- a/components/system/Files/Views/StyledRenameBox.ts +++ b/components/system/Files/Views/StyledRenameBox.ts @@ -9,12 +9,13 @@ const StyledRenameBox = styled.textarea.attrs({ font-family: inherit; font-size: 11.5px; margin-bottom: 2px; - padding: 1px 5px; + overflow: hidden; + padding: ${({ theme }) => `1px ${theme.sizes.fileEntry.renamePadding}px`}; position: relative; resize: none; text-align: center; top: 2px; - width: 70px; + width: ${({ theme }) => `${theme.sizes.fileEntry.renameWidth}px`}; `; export default StyledRenameBox; diff --git a/components/system/Files/Views/index.ts b/components/system/Files/Views/index.ts index 812accd3..f5e6db8e 100644 --- a/components/system/Files/Views/index.ts +++ b/components/system/Files/Views/index.ts @@ -10,6 +10,7 @@ export type StyledFileEntryProps = { }; export type StyledFileManagerProps = { + scrollable: boolean; selecting: boolean; }; diff --git a/pages/index.tsx b/pages/index.tsx index 1a770040..5e7ba4e4 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -11,7 +11,12 @@ const Home = (): React.ReactElement => { return ( - + diff --git a/styles/GlobalStyle.ts b/styles/GlobalStyle.ts index 939bc73c..113ce787 100644 --- a/styles/GlobalStyle.ts +++ b/styles/GlobalStyle.ts @@ -13,7 +13,7 @@ const GlobalStyle = createGlobalStyle` } body { - font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-family: ${({ theme }) => theme.formats.systemFont}; overflow: hidden; } diff --git a/styles/defaultTheme/formats.ts b/styles/defaultTheme/formats.ts index 3b65b3ec..e51c828d 100644 --- a/styles/defaultTheme/formats.ts +++ b/styles/defaultTheme/formats.ts @@ -15,6 +15,8 @@ const formats = { minute: "2-digit", hour12: true, } as Intl.DateTimeFormatOptions, + systemFont: + "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif", }; export default formats; diff --git a/styles/defaultTheme/sizes.ts b/styles/defaultTheme/sizes.ts index c346aae7..81ca4502 100644 --- a/styles/defaultTheme/sizes.ts +++ b/styles/defaultTheme/sizes.ts @@ -9,6 +9,8 @@ const sizes = { fileEntry: { fontSize: "12px", iconSize: "48px", + renamePadding: 5, + renameWidth: 75, }, fileManager: { columnGap: "1px",