Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
chore: Merge pull request #44 from alist-org/dev
Browse files Browse the repository at this point in the history
Dev 2.5.0
  • Loading branch information
xhofe authored May 7, 2022
2 parents 524e808 + 3f3722e commit 38965d9
Show file tree
Hide file tree
Showing 10 changed files with 318 additions and 37 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@choc-ui/paginator": "^3.4.0",
"@emotion/react": "^11.8.1",
"@emotion/styled": "^11.8.1",
"@monaco-editor/react": "^4.4.4",
"@xhofe/react-viewer": "^3.2.3",
"artplayer": "^4.3.1",
"axios": "^0.26.0",
Expand All @@ -37,6 +38,7 @@
"hls.js": "^1.1.5",
"i18next": "^21.6.12",
"mitt": "^3.0.0",
"monaco-editor": "^0.33.0",
"react": "^17.0.0",
"react-contexify": "^5.0.0",
"react-dom": "^17.0.0",
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/locales/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ const zh = {
"Backup": "备份",
"Restore": "还原",
"Virtual path": "虚拟路径",
"Send to Aria2": "发送到Aria2",
"Send {{number}} links to Aria2": "发送 {{number}} 个链接到Aria2",
"Can't download folder with Aria2": "Aria2不能下载文件夹",
"Sent": "已发送",
}

export default zh
Expand Down
31 changes: 31 additions & 0 deletions src/pages/list/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ interface Page {
page_size: number;
}

interface Aria2 {
rpcUrl: string;
rpcSecret: string;
}

export interface ContextProps {
files: File[];
setFiles: (files: File[]) => void;
Expand Down Expand Up @@ -113,6 +118,8 @@ export interface ContextProps {
page: Page;
setPage: (page: Page) => void;
hideFiles: RegExp[];
aria2: Aria2;
setAria2: (aria2: Aria2) => void;
}

export const IContext = createContext<ContextProps>({
Expand Down Expand Up @@ -140,6 +147,8 @@ export const IContext = createContext<ContextProps>({
page: { page_num: 1, page_size: 30 },
setPage: () => {},
hideFiles: [],
aria2: { rpcUrl: "", rpcSecret: "" },
setAria2: () => {},
});

const IContextProvider = (props: any) => {
Expand Down Expand Up @@ -169,6 +178,11 @@ const IContextProvider = (props: any) => {
page_size: 30,
});

const [aria2, setAria2] = React.useState<Aria2>({
rpcUrl: "",
rpcSecret: "",
});

const [hideFiles, setHideFiles] = React.useState<RegExp[]>([]);
const darkMode = useColorModeValue(false, true);

Expand Down Expand Up @@ -253,9 +267,25 @@ const IContextProvider = (props: any) => {
});
}, []);

const aria2Config = useCallback(() => {
admin.get("settings?group=1").then((resp) => {
let res = resp.data;
if (res.code === 200) {
let setting: Setting[] = res.data;
let url = setting.find((item) => item.key === "Aria2 RPC url");
let secret = setting.find((item) => item.key === "Aria2 RPC secret");
setAria2({
rpcUrl: url?.value || "",
rpcSecret: secret?.value || "",
});
}
});
}, []);

useEffect(() => {
initialSettings();
login();
aria2Config();
}, []);

const [showUnfold, setShowUnfold] = React.useState<boolean>(false);
Expand Down Expand Up @@ -309,6 +339,7 @@ const IContextProvider = (props: any) => {
page,
setPage,
hideFiles,
aria2,
}}
{...props}
/>
Expand Down
70 changes: 67 additions & 3 deletions src/pages/list/layout/files/contextmenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,21 @@ import {
FcNumericalSorting12,
FcClock,
FcRefresh,
FcDownload,
} from "react-icons/fc";
import { MdDeleteForever } from "react-icons/md";
import useFileUrl from "../../../../hooks/useFileUrl";
import useDownPackage from "../../../../hooks/useDownPackage";
import { copyToClip } from "../../../../utils/copy-clip";
import admin from "../../../../utils/admin";
import { useLocation } from "react-router-dom";
import { useLocation, useHistory } from "react-router-dom";
import bus from "../../../../utils/event-bus";
import NewFolder, { NewFolderInput } from "./menus/new-folder";
import Rename, { RenameInput } from "./menus/rename";
import Move, { MoveSelect } from "./menus/move";
import Copy, { CopySelect } from "./menus/copy";
import Refresh from "./menus/refresh";
import { downloadWithAria2 } from "~/utils/aria2";

export const MENU_ID = "list-menu";

Expand All @@ -43,8 +45,16 @@ interface IsOpenSet {

const ContextMenu = () => {
const { t } = useTranslation();
const { sort, setSort, multiSelect, setMultiSelect, selectFiles, loggedIn } =
useContext(IContext);
const {
sort,
setSort,
multiSelect,
setMultiSelect,
selectFiles,
loggedIn,
aria2,
} = useContext(IContext);
const history = useHistory();
const menuTheme = useColorModeValue(theme.light, theme.dark);
const toast = useToast();
const getFileUrl = useFileUrl();
Expand Down Expand Up @@ -158,6 +168,60 @@ const ContextMenu = () => {
</Flex>
</Item>

{loggedIn && (
<Item
disabled={isItemDisabled}
onClick={({ props }) => {
let content = "";
if (multiSelect) {
content = selectFiles
.filter((file) => file.type !== 1)
.map((file) => {
return getFileUrlDecode(file);
})
.join("\n");
} else {
const file = props as File;
if (file.type === 1) {
toast({
title: t("Can't download folder with Aria2"),
status: "warning",
duration: 3000,
isClosable: true,
});
return;
}
content = getFileUrlDecode(file);
}
if (!aria2.rpcUrl) {
toast({
title: t("Aria2 is not configured"),
status: "error",
duration: 3000,
isClosable: true,
});
} else {
downloadWithAria2(content, aria2);
toast({
title: t("Sent"),
status: "success",
duration: 3000,
isClosable: true,
});
}
}}
>
<Flex align="center">
<Icon as={FcDownload} boxSize={5} mr={2} />
{multiSelect
? t("Send {{number}} links to Aria2", {
number: selectFiles.length,
})
: t("Send to Aria2")}
</Flex>
</Item>
)}

<Item
disabled={isItemDisabled}
onClick={({ props }) => {
Expand Down
6 changes: 3 additions & 3 deletions src/pages/list/layout/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ const Search = (props: SearchProps) => {
inputRef.current?.focus();
}
const switchSearch = (e: KeyboardEvent) => {
if (["f", "F"].includes(e.key) && e.ctrlKey) {
if (["k", "K"].includes(e.key) && e.ctrlKey) {
props.setIsSearch(!props.isSearch);
e.preventDefault();
}
};
document.addEventListener("keydown", switchSearch);
if(getSetting("enable search") === "true"){document.addEventListener("keydown", switchSearch);}
const cancelSearch = (e: MouseEvent) => {
props.setIsSearch(false);
};
Expand All @@ -40,7 +40,7 @@ const Search = (props: SearchProps) => {
document.removeEventListener("click", cancelSearch);
};
}, [props.isSearch]);
// if (!getSetting("enable search")) return null;
if (getSetting("enable search") !== "true") return null;
return (
<HStack
spacing={2}
Expand Down
6 changes: 4 additions & 2 deletions src/pages/list/preview/audio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const Audio = ({ file }: FileProps) => {
getSetting("music cover") ||
"https://store.heytapimage.com/cdo-portal/feedback/202110/30/d43c41c5d257c9bc36366e310374fb19.png";
const singer = t("unknown");
const [playIndex, setPlayIndex] = React.useState(0);
useEffect(() => {
const audio: ReactJkMusicPlayerAudioListProps = {
name: file.name,
Expand Down Expand Up @@ -68,7 +69,7 @@ const Audio = ({ file }: FileProps) => {
} else {
setAudioLists([audio]);
}
// setAudioLists([audio, ...audioList]);
setPlayIndex(audioList.findIndex((item) => item.name === file.name));
}, []);
return (
<Box className="audio-box" w="full">
Expand All @@ -91,7 +92,8 @@ const Audio = ({ file }: FileProps) => {
left: 20,
bottom: 20,
}}
playIndex={audioLists.findIndex((item) => item.name === file.name)}
playIndex={playIndex}
onPlayIndexChange={setPlayIndex}
sortableOptions={{ disabled: mobile }}
defaultVolume={volume}
onAudioVolumeChange={(v) => setVolume(v)}
Expand Down
115 changes: 115 additions & 0 deletions src/pages/list/preview/codeeditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Integrating the ESM version of the Monaco Editor
// https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md#using-vite

// import * as monaco from 'monaco-editor';
// self.MonacoEnvironment = {
// getWorker: function (workerId, label) {
// const getWorkerModule = (moduleUrl, label) => {
// return new Worker(self.MonacoEnvironment.getWorkerUrl(moduleUrl), {
// name: label,
// type: 'module'
// });
// };

// switch (label) {
// case 'json':
// return getWorkerModule('/monaco-editor/esm/vs/language/json/json.worker?worker', label);
// case 'css':
// case 'scss':
// case 'less':
// return getWorkerModule('/monaco-editor/esm/vs/language/css/css.worker?worker', label);
// case 'html':
// case 'handlebars':
// case 'razor':
// return getWorkerModule('/monaco-editor/esm/vs/language/html/html.worker?worker', label);
// case 'typescript':
// case 'javascript':
// return getWorkerModule('/monaco-editor/esm/vs/language/typescript/ts.worker?worker', label);
// default:
// return getWorkerModule('/monaco-editor/esm/vs/editor/editor.worker?worker', label);
// }
// }
// };

import Editor from "@monaco-editor/react";
import {
Box,
Select,
Button,
Flex,
Spacer,
useColorModeValue,
useToast,
Heading,
} from "@chakra-ui/react";
import React from "react";
import axios from "axios";
import { useLocation } from "react-router-dom";
import { useTranslation } from "react-i18next";
import useFileUrl from "../../../hooks/useFileUrl";
import { FileProps } from "../context";
import request from "../../../utils/public";

export const type = -1;
export const exts = [];

const CodeEditor = ({ file }: FileProps) => {
const theme = useColorModeValue("light", "dark");
const { t } = useTranslation();
const toast = useToast();
const { pathname } = useLocation();

const [content, setContent] = React.useState<string | undefined>("");

let link = useFileUrl(true)(file);
const getContent = () => {
axios.get(link).then(async (resp) => {
setContent(resp.data);
});
};

const handleSaveButton: React.MouseEventHandler = async () => {
const folder = pathname.substring(0, pathname.lastIndexOf("/") || 1);
const form = new FormData();
form.append("files", new Blob([content as string]), file.name);
form.append("path", folder);
request
.post("upload", form, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((resp) => {
const res = resp.data;
toast({
title: t(res.message),
status: res.code === 200 ? "success" : "error",
duration: 3000,
isClosable: true,
});
});
};
React.useEffect(() => {
getContent();
}, []);

return (
<Box>
<Editor
height="70vh"
value={content}
path={file.name}
theme={theme === "light" ? "light" : "vs-dark"}
onChange={(value) => setContent(value)}
/>
<Flex m="2">
<Spacer />
<Button mt="5" onClick={handleSaveButton}>
{t("Save")}
</Button>
</Flex>
</Box>
);
};

export default CodeEditor;
Loading

0 comments on commit 38965d9

Please sign in to comment.