mirror of
https://github.com/DustinBrett/daedalOS.git
synced 2025-12-06 00:20:05 +01:00
Better loading/empty visuals
This commit is contained in:
parent
8708b3a230
commit
e992b6b0ec
|
|
@ -1,5 +1,5 @@
|
|||
import styled from "styled-components";
|
||||
import StyledLoading from "components/system/Files/FileManager/StyledLoading";
|
||||
import StyledLoading from "components/system/Apps/StyledLoading";
|
||||
import StyledDetailsFileManager from "components/system/Files/Views/Details/StyledFileManager";
|
||||
import StyledIconFileManager from "components/system/Files/Views/Icon/StyledFileManager";
|
||||
|
||||
|
|
@ -21,6 +21,7 @@ const StyledFileExplorer = styled.div`
|
|||
${StyledLoading} {
|
||||
height: ${({ theme }) =>
|
||||
`calc(100% - ${theme.sizes.fileExplorer.navBarHeight} - ${theme.sizes.fileExplorer.statusBarHeight})`};
|
||||
position: absolute;
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
import { getNetworkConfig } from "components/apps/IRC/config";
|
||||
import { type ComponentProcessProps } from "components/system/Apps/RenderComponent";
|
||||
import StyledLoading from "components/system/Files/FileManager/StyledLoading";
|
||||
import StyledLoading from "components/system/Apps/StyledLoading";
|
||||
import { useProcesses } from "contexts/process";
|
||||
import processDirectory from "contexts/process/directory";
|
||||
import { IFRAME_CONFIG } from "utils/constants";
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { basename, dirname, join } from "path";
|
|||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import StyledPaint from "components/apps/Paint/StyledPaint";
|
||||
import { type ComponentProcessProps } from "components/system/Apps/RenderComponent";
|
||||
import StyledLoading from "components/system/Files/FileManager/StyledLoading";
|
||||
import StyledLoading from "components/system/Apps/StyledLoading";
|
||||
import useFileDrop from "components/system/Files/FileManager/useFileDrop";
|
||||
import useTitle from "components/system/Window/useTitle";
|
||||
import { useFileSystem } from "contexts/fileSystem";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { memo, useMemo, useRef, useState } from "react";
|
||||
import styled, { type IStyledComponent } from "styled-components";
|
||||
import { type FastOmit } from "styled-components/dist/types";
|
||||
import StyledLoading from "components/system/Files/FileManager/StyledLoading";
|
||||
import StyledLoading from "components/system/Apps/StyledLoading";
|
||||
import useFileDrop from "components/system/Files/FileManager/useFileDrop";
|
||||
import { useProcesses } from "contexts/process";
|
||||
|
||||
|
|
|
|||
29
components/system/Apps/StyledLoading.ts
Normal file
29
components/system/Apps/StyledLoading.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import styled from "styled-components";
|
||||
|
||||
type StyledLoadingProps = {
|
||||
$hasColumns?: boolean;
|
||||
};
|
||||
|
||||
const StyledLoading = styled.div<StyledLoadingProps>`
|
||||
cursor: wait;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
&::before {
|
||||
color: #fff;
|
||||
content: "Working on it...";
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
font-weight: 200;
|
||||
justify-content: center;
|
||||
letter-spacing: 0.3px;
|
||||
mix-blend-mode: difference;
|
||||
padding-top: ${({ $hasColumns, theme }) =>
|
||||
$hasColumns
|
||||
? theme.sizes.window.textTopPadding +
|
||||
theme.sizes.fileManager.columnHeight
|
||||
: theme.sizes.window.textTopPadding}px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledLoading;
|
||||
|
|
@ -12,7 +12,7 @@ const StyledColumns = styled.span`
|
|||
|
||||
ol {
|
||||
display: flex;
|
||||
height: ${({ theme }) => theme.sizes.fileManager.columnHeight};
|
||||
height: ${({ theme }) => theme.sizes.fileManager.columnHeight}px;
|
||||
|
||||
li {
|
||||
color: rgb(222 222 222);
|
||||
|
|
@ -46,7 +46,7 @@ const StyledColumns = styled.span`
|
|||
.resize {
|
||||
border-left: 1px solid rgb(99 99 99);
|
||||
cursor: col-resize;
|
||||
height: 25px;
|
||||
height: ${({ theme }) => theme.sizes.fileManager.columnHeight}px;
|
||||
padding-left: ${({ theme }) =>
|
||||
theme.sizes.fileManager.columnResizeWidth}px;
|
||||
position: absolute;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { memo, useRef } from "react";
|
||||
import { memo, useCallback, useRef } from "react";
|
||||
import { useTheme } from "styled-components";
|
||||
import dynamic from "next/dynamic";
|
||||
import { sortFiles } from "components/system/Files/FileManager/functions";
|
||||
|
|
@ -35,6 +35,64 @@ const Columns: FC<ColumnsProps> = ({
|
|||
const lastClientX = useRef(0);
|
||||
const { setSortOrder, sortOrders } = useSession();
|
||||
const [, sortedBy = "name", ascending] = sortOrders[directory] ?? [];
|
||||
const onPointerDownCapture = useCallback(
|
||||
(name: string) => (event: React.PointerEvent<HTMLLIElement>) => {
|
||||
if (event.button !== 0) return;
|
||||
|
||||
draggingRef.current =
|
||||
(event.target as HTMLElement).className === "resize" ? name : "";
|
||||
lastClientX.current = event.clientX;
|
||||
},
|
||||
[]
|
||||
);
|
||||
const onPointerMoveCapture = useCallback(
|
||||
(event: React.PointerEvent<HTMLLIElement>) => {
|
||||
if (draggingRef.current) {
|
||||
const dragName = draggingRef.current as ColumnName;
|
||||
|
||||
setColumns((currentColumns) => {
|
||||
if (!currentColumns?.[dragName]) return currentColumns;
|
||||
|
||||
const newColumns = { ...currentColumns };
|
||||
const newSize =
|
||||
newColumns[dragName].width + event.clientX - lastClientX.current;
|
||||
|
||||
if (
|
||||
newSize < sizes.fileManager.columnMinWidth ||
|
||||
Math.abs(lastClientX.current - event.clientX) > MAX_STEPS_PER_RESIZE
|
||||
) {
|
||||
return newColumns;
|
||||
}
|
||||
|
||||
newColumns[dragName].width = newSize;
|
||||
lastClientX.current = event.clientX;
|
||||
|
||||
return newColumns;
|
||||
});
|
||||
}
|
||||
},
|
||||
[setColumns, sizes.fileManager.columnMinWidth]
|
||||
);
|
||||
const onPointerUpCapture = useCallback(
|
||||
(name: string) => (event: React.PointerEvent<HTMLLIElement>) => {
|
||||
if (event.button !== 0) return;
|
||||
|
||||
if (draggingRef.current) {
|
||||
draggingRef.current = "";
|
||||
lastClientX.current = 0;
|
||||
} else {
|
||||
const sortBy = name as SortBy;
|
||||
|
||||
setSortOrder(
|
||||
directory,
|
||||
Object.keys(sortFiles(directory, files, sortBy, !ascending)),
|
||||
sortBy,
|
||||
!ascending
|
||||
);
|
||||
}
|
||||
},
|
||||
[ascending, directory, files, setSortOrder]
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledColumns>
|
||||
|
|
@ -42,60 +100,9 @@ const Columns: FC<ColumnsProps> = ({
|
|||
{DEFAULT_COLUMN_ORDER.map((name) => (
|
||||
<li
|
||||
key={columns[name].name}
|
||||
onPointerDownCapture={(event) => {
|
||||
if (event.button !== 0) return;
|
||||
|
||||
draggingRef.current =
|
||||
(event.target as HTMLElement).className === "resize"
|
||||
? name
|
||||
: "";
|
||||
lastClientX.current = event.clientX;
|
||||
}}
|
||||
onPointerMoveCapture={(event) => {
|
||||
if (draggingRef.current) {
|
||||
const dragName = draggingRef.current as ColumnName;
|
||||
|
||||
setColumns((currentColumns) => {
|
||||
if (!currentColumns?.[dragName]) return currentColumns;
|
||||
|
||||
const newColumns = { ...currentColumns };
|
||||
const newSize =
|
||||
newColumns[dragName].width +
|
||||
event.clientX -
|
||||
lastClientX.current;
|
||||
|
||||
if (
|
||||
newSize < sizes.fileManager.columnMinWidth ||
|
||||
Math.abs(lastClientX.current - event.clientX) >
|
||||
MAX_STEPS_PER_RESIZE
|
||||
) {
|
||||
return newColumns;
|
||||
}
|
||||
|
||||
newColumns[dragName].width = newSize;
|
||||
lastClientX.current = event.clientX;
|
||||
|
||||
return newColumns;
|
||||
});
|
||||
}
|
||||
}}
|
||||
onPointerUpCapture={(event) => {
|
||||
if (event.button !== 0) return;
|
||||
|
||||
if (draggingRef.current) {
|
||||
draggingRef.current = "";
|
||||
lastClientX.current = 0;
|
||||
} else {
|
||||
const sortBy = name as SortBy;
|
||||
|
||||
setSortOrder(
|
||||
directory,
|
||||
Object.keys(sortFiles(directory, files, sortBy, !ascending)),
|
||||
sortBy,
|
||||
!ascending
|
||||
);
|
||||
}
|
||||
}}
|
||||
onPointerDownCapture={onPointerDownCapture(name)}
|
||||
onPointerMoveCapture={onPointerMoveCapture}
|
||||
onPointerUpCapture={onPointerUpCapture(name)}
|
||||
style={{ width: `${columns[name].width}px` }}
|
||||
>
|
||||
{sortedBy === name && <Down flip={ascending} />}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import styled from "styled-components";
|
||||
|
||||
const StyledEmpty = styled.div`
|
||||
type StyledEmptyProps = {
|
||||
$hasColumns?: boolean;
|
||||
};
|
||||
|
||||
const StyledEmpty = styled.div<StyledEmptyProps>`
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
||||
|
|
@ -13,7 +17,11 @@ const StyledEmpty = styled.div`
|
|||
justify-content: center;
|
||||
letter-spacing: 0.3px;
|
||||
mix-blend-mode: difference;
|
||||
padding-top: 14px;
|
||||
padding-top: ${({ $hasColumns, theme }) =>
|
||||
$hasColumns
|
||||
? theme.sizes.window.textTopPadding +
|
||||
theme.sizes.fileManager.columnHeight
|
||||
: theme.sizes.window.textTopPadding}px;
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
import styled from "styled-components";
|
||||
|
||||
const StyledLoading = styled.div`
|
||||
cursor: wait;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
&::before {
|
||||
color: #fff;
|
||||
content: "Working on it...";
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
justify-content: center;
|
||||
mix-blend-mode: difference;
|
||||
padding-top: 18px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledLoading;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { basename, join } from "path";
|
||||
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
import StyledLoading from "components/system/Files/FileManager/StyledLoading";
|
||||
import StyledLoading from "components/system/Apps/StyledLoading";
|
||||
import StatusBar from "components/system/Files/FileManager/StatusBar";
|
||||
import {
|
||||
DEFAULT_COLUMNS,
|
||||
|
|
@ -85,11 +85,12 @@ const FileManager: FC<FileManagerProps> = ({
|
|||
const [renaming, setRenaming] = useState("");
|
||||
const [mounted, setMounted] = useState<boolean>(false);
|
||||
const fileManagerRef = useRef<HTMLOListElement | null>(null);
|
||||
const isFileExplorerIconView = useMemo(
|
||||
() => !isStartMenu && !isDesktop && !isDetailsView,
|
||||
[isDesktop, isDetailsView, isStartMenu]
|
||||
);
|
||||
const { focusedEntries, focusableEntry, ...focusFunctions } =
|
||||
useFocusableEntries(
|
||||
fileManagerRef,
|
||||
!isStartMenu && !isDesktop && !isDetailsView
|
||||
);
|
||||
useFocusableEntries(fileManagerRef, isFileExplorerIconView);
|
||||
const { fileActions, files, folderActions, isLoading, updateFiles } =
|
||||
useFolder(url, setRenaming, focusFunctions, {
|
||||
hideFolders,
|
||||
|
|
@ -121,7 +122,11 @@ const FileManager: FC<FileManagerProps> = ({
|
|||
isDesktop,
|
||||
isStartMenu
|
||||
);
|
||||
const loading = (!hideLoading && isLoading) || url !== currentUrl;
|
||||
const loading = useMemo(() => {
|
||||
if (hideLoading) return false;
|
||||
|
||||
return isLoading || url !== currentUrl;
|
||||
}, [currentUrl, hideLoading, isLoading, url]);
|
||||
const setView = useCallback(
|
||||
(newView: FileManagerViewNames) => {
|
||||
setViews((currentViews) => ({ ...currentViews, [url]: newView }));
|
||||
|
|
@ -151,12 +156,10 @@ const FileManager: FC<FileManagerProps> = ({
|
|||
[keyShortcuts, renaming]
|
||||
);
|
||||
const fileKeys = useMemo(() => Object.keys(files), [files]);
|
||||
const isEmptyFolder =
|
||||
!isDesktop &&
|
||||
!isStartMenu &&
|
||||
!loading &&
|
||||
view !== "list" &&
|
||||
fileKeys.length === 0;
|
||||
const isEmptyFolder = useMemo(
|
||||
() => !isDesktop && !isStartMenu && !loading && fileKeys.length === 0,
|
||||
[fileKeys.length, isDesktop, isStartMenu, loading]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
|
|
@ -231,34 +234,33 @@ const FileManager: FC<FileManagerProps> = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
{loading ? (
|
||||
<StyledLoading />
|
||||
) : (
|
||||
<>
|
||||
{isEmptyFolder && <StyledEmpty />}
|
||||
<StyledFileManager
|
||||
ref={fileManagerRef}
|
||||
$isEmptyFolder={isEmptyFolder}
|
||||
$scrollable={!hideScrolling}
|
||||
onKeyDownCapture={onKeyDown}
|
||||
{...(readOnly
|
||||
? { onContextMenu: haltEvent }
|
||||
: {
|
||||
$selecting: isSelecting,
|
||||
...fileDrop,
|
||||
...folderContextMenu,
|
||||
...selectionEvents,
|
||||
})}
|
||||
{...FOCUSABLE_ELEMENT}
|
||||
>
|
||||
{isDetailsView && columns && (
|
||||
<Columns
|
||||
columns={columns}
|
||||
directory={url}
|
||||
files={files}
|
||||
setColumns={setColumns}
|
||||
/>
|
||||
)}
|
||||
{loading && <StyledLoading $hasColumns={isDetailsView} />}
|
||||
{!loading && isEmptyFolder && <StyledEmpty $hasColumns={isDetailsView} />}
|
||||
<StyledFileManager
|
||||
ref={fileManagerRef}
|
||||
$isEmptyFolder={isEmptyFolder}
|
||||
$scrollable={!hideScrolling}
|
||||
onKeyDownCapture={loading ? undefined : onKeyDown}
|
||||
{...(loading || readOnly
|
||||
? { onContextMenu: haltEvent }
|
||||
: {
|
||||
$selecting: isSelecting,
|
||||
...fileDrop,
|
||||
...folderContextMenu,
|
||||
...selectionEvents,
|
||||
})}
|
||||
{...FOCUSABLE_ELEMENT}
|
||||
>
|
||||
{isDetailsView && columns && (
|
||||
<Columns
|
||||
columns={columns}
|
||||
directory={url}
|
||||
files={files}
|
||||
setColumns={setColumns}
|
||||
/>
|
||||
)}
|
||||
{!loading && (
|
||||
<>
|
||||
{isSelecting && <StyledSelection style={selectionStyling} />}
|
||||
{fileKeys.map((file) => (
|
||||
<StyledFileEntry
|
||||
|
|
@ -294,9 +296,9 @@ const FileManager: FC<FileManagerProps> = ({
|
|||
/>
|
||||
</StyledFileEntry>
|
||||
))}
|
||||
</StyledFileManager>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</StyledFileManager>
|
||||
{showStatusBar && (
|
||||
<StatusBar
|
||||
count={loading ? 0 : fileKeys.length}
|
||||
|
|
|
|||
|
|
@ -168,8 +168,10 @@ const useFolder = (
|
|||
},
|
||||
[directory, readFile]
|
||||
);
|
||||
const isSimpleSort =
|
||||
skipSorting || !sortBy || sortBy === "name" || sortBy === "type";
|
||||
const isSimpleSort = useMemo(
|
||||
() => skipSorting || !sortBy || sortBy === "name" || sortBy === "type",
|
||||
[skipSorting, sortBy]
|
||||
);
|
||||
const updateFiles = useCallback(
|
||||
async (newFile?: string, oldFile?: string) => {
|
||||
if (oldFile) {
|
||||
|
|
@ -739,6 +741,7 @@ const useFolder = (
|
|||
|
||||
useEffect(() => {
|
||||
if (directory !== currentDirectory) {
|
||||
setIsLoading(true);
|
||||
setCurrentDirectory(directory);
|
||||
setFiles(NO_FILES);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { m as motion } from "motion/react";
|
||||
import styled from "styled-components";
|
||||
import StyledLoading from "components/system/Files/FileManager/StyledLoading";
|
||||
import StyledLoading from "components/system/Apps/StyledLoading";
|
||||
|
||||
type StyledWindowProps = {
|
||||
$backgroundBlur?: string;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const sizes = {
|
|||
},
|
||||
fileManager: {
|
||||
columnGap: "1px",
|
||||
columnHeight: "25px",
|
||||
columnHeight: 25,
|
||||
columnMinWidth: 70,
|
||||
columnResizeWidth: 7,
|
||||
detailsEndPadding: 16,
|
||||
|
|
@ -87,6 +87,7 @@ const sizes = {
|
|||
window: {
|
||||
cascadeOffset: 26,
|
||||
outline: "1px",
|
||||
textTopPadding: 14,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user