fix: incorrect handling of pathname encoding

This commit is contained in:
Aaron Liu 2025-05-13 17:34:38 +08:00
parent 571df0f911
commit f1c048ec0b
4 changed files with 29 additions and 77 deletions

View File

@ -1,34 +1,16 @@
import { Box, ClickAwayListener, Menu, styled, TextField, useMediaQuery, useTheme } from "@mui/material";
import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import { useIsOverflow } from "../../../hooks/useOverflow.tsx";
import { useAppDispatch, useAppSelector } from "../../../redux/hooks.ts";
import {
Box,
ClickAwayListener,
Menu,
styled,
TextField,
useMediaQuery,
useTheme,
} from "@mui/material";
import React, {
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import BreadcrumbButton, {
BreadcrumbButtonBase,
BreadcrumbButtonProps,
} from "./BreadcrumbButton.tsx";
import { navigateToPath } from "../../../redux/thunks/filemanager.ts";
import { mergeRefs } from "../../../util";
import CrUri from "../../../util/uri.ts";
import ChevronRight from "../../Icons/ChevronRight.tsx";
import MoreHorizontal from "../../Icons/MoreHorizontal.tsx";
import { useIsOverflow } from "../../../hooks/useOverflow.tsx";
import { mergeRefs } from "../../../util";
import BreadcrumbHiddenItem from "./BreadcrumbHiddenItem.tsx";
import { NoOpDropUri, useFileDrag } from "../Dnd/DndWrappedFile.tsx";
import { navigateToPath } from "../../../redux/thunks/filemanager.ts";
import { FmIndexContext } from "../FmIndexContext.tsx";
import BreadcrumbButton, { BreadcrumbButtonBase, BreadcrumbButtonProps } from "./BreadcrumbButton.tsx";
import BreadcrumbHiddenItem from "./BreadcrumbHiddenItem.tsx";
const PathTextField = styled(TextField)(() => ({
"& .MuiOutlinedInput-notchedOutline": {
@ -63,9 +45,7 @@ const useBreadcrumb = (targetPath?: string) => {
const index = useContext(FmIndexContext);
const base = useAppSelector(
(s) => s.fileManager[index].path_root_with_category,
);
const base = useAppSelector((s) => s.fileManager[index].path_root_with_category);
const path = useAppSelector((s) => s.fileManager[index].path);
const elements = useAppSelector((s) => s.fileManager[index].path_elements);
@ -204,10 +184,7 @@ const Breadcrumb = (props: BreadcrumbProps) => {
onClick={onEdit}
>
{editing && (
<ClickAwayListener
mouseEvent={"onMouseDown"}
onClickAway={() => submitNewPath()}
>
<ClickAwayListener mouseEvent={"onMouseDown"} onClickAway={() => submitNewPath()}>
<PathTextField
autoFocus
onFocus={(e) => {
@ -257,17 +234,11 @@ const Breadcrumb = (props: BreadcrumbProps) => {
slotProps={{
list: {
dense: true,
}
},
}}
>
{hidedButtons &&
hidedButtons.map((b) => (
<BreadcrumbHiddenItem
key={b.path}
onClose={() => setAnchorEl(null)}
{...b}
/>
))}
hidedButtons.map((b) => <BreadcrumbHiddenItem key={b.path} onClose={() => setAnchorEl(null)} {...b} />)}
</Menu>
</>
);

View File

@ -1,13 +1,13 @@
import React, { useContext, useMemo } from "react";
import TreeFile from "./TreeFile.tsx";
import CrUri, { Filesystem } from "../../../util/uri.ts";
import { useAppSelector } from "../../../redux/hooks.ts";
import { useTranslation } from "react-i18next";
import { useBreadcrumbButtons } from "../TopBar/BreadcrumbButton.tsx";
import path from "path-browserify";
import { Box } from "@mui/material";
import path from "path-browserify";
import React, { useContext, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { useAppSelector } from "../../../redux/hooks.ts";
import CrUri, { Filesystem } from "../../../util/uri.ts";
import SideNavItem from "../../Frame/NavBar/SideNavItem.tsx";
import { FmIndexContext } from "../FmIndexContext.tsx";
import { useBreadcrumbButtons } from "../TopBar/BreadcrumbButton.tsx";
import TreeFile from "./TreeFile.tsx";
export interface TreeFilesProps {
path: string;
@ -26,24 +26,12 @@ export const pinedPrefix = "Pined";
const TreeFiles = React.memo(
React.forwardRef(
(
{
path: p,
level,
elements,
labelOverwrite,
notLoaded,
pinned,
flatten,
canDrop,
...rest
}: TreeFilesProps,
{ path: p, level, elements, labelOverwrite, notLoaded, pinned, flatten, canDrop, ...rest }: TreeFilesProps,
ref: React.Ref<HTMLLIElement>,
) => {
const { t } = useTranslation();
const fmIndex = useContext(FmIndexContext);
const parentsCache = useAppSelector(
(state) => state.fileManager[fmIndex].tree[p],
);
const parentsCache = useAppSelector((state) => state.fileManager[fmIndex].tree[p]);
const [limit, setLimit] = React.useState(50);
const uri = useMemo(() => new CrUri(p), [p]);
const nodeId = useMemo(() => {
@ -54,10 +42,7 @@ const TreeFiles = React.memo(
return p;
}, [pinned, p, flatten]);
const [loading, displayName, startIcon, onClick] = useBreadcrumbButtons({
name:
parentsCache && parentsCache.file
? parentsCache.file.name
: path.basename(uri.path()),
name: parentsCache && parentsCache.file ? parentsCache.file.name : path.basename(uri.path()),
is_latest: false,
path: p,
});
@ -109,10 +94,7 @@ const TreeFiles = React.memo(
}, [p, elements, parentsCache, limit]);
const shadowChild = useMemo(() => {
if (
flatten ||
(parentsCache?.children && parentsCache.children.length == 0)
) {
if (flatten || (parentsCache?.children && parentsCache.children.length == 0)) {
return null;
}
return <Box />;
@ -150,11 +132,7 @@ const TreeFiles = React.memo(
: shadowChild}
</TreeFile>
{limit < childTreeFiles.length ? (
<SideNavItem
level={level + 1}
label={t("navbar.showMore")}
onClick={() => setLimit((l) => l + 50)}
/>
<SideNavItem level={level + 1} label={t("navbar.showMore")} onClick={() => setLimit((l) => l + 50)} />
) : null}
</>
);

View File

@ -333,7 +333,7 @@ const VideoViewer = () => {
url = url.replace(CrMaskedPrefix, "");
const currentFileUrl = new CrUri(getFileLinkedUri(viewerState.file));
const base = new CrUri(currentFileUrl.base());
const realUrl = base.join(url);
const realUrl = base.join(...url.split("/"));
try {
const res = await dispatch(getFileEntityUrl({ uris: [realUrl.toString()] }));
return res.urls[0];

View File

@ -196,11 +196,14 @@ export default class CrUri {
}
public path(): string {
return this.url.pathname;
return decodeURIComponent(this.url.pathname);
}
public setPath(path: string): this {
this.url.pathname = path;
this.url.pathname = path
.split("/")
.map((p) => encodeURIComponent(p))
.join("/");
return this;
}