Add file load UI
This commit is contained in:
@@ -1,10 +1,16 @@
|
||||
@import "../Theme/Theme.scss";
|
||||
|
||||
div.load-file-app-root {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
div.load-file-layer-root {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
box-sizing: border-box;
|
||||
padding: 20px;
|
||||
|
||||
@@ -19,7 +25,6 @@ div.load-file-layer-root {
|
||||
border-radius: 3px;
|
||||
|
||||
div {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
@@ -1,69 +1,142 @@
|
||||
import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup";
|
||||
import { Localization } from "@Component/Localization/Localization";
|
||||
import { FontLevel, Theme } from "@Component/Theme/Theme";
|
||||
import { Status, useStatus, IMixinStatusProps } from "@Context/Status";
|
||||
import { Icon } from "@fluentui/react";
|
||||
import { Component, ReactNode } from "react";
|
||||
import { FunctionComponent } from "react";
|
||||
import { useDrop } from 'react-dnd'
|
||||
import { NativeTypes } from "react-dnd-html5-backend"
|
||||
import "./LoadFile.scss";
|
||||
|
||||
interface ILoadFileState {
|
||||
show: boolean;
|
||||
}
|
||||
const DragFileMask: FunctionComponent = () => {
|
||||
|
||||
class LoadFile extends Component<{}, ILoadFileState> {
|
||||
|
||||
public state: Readonly<ILoadFileState> = {
|
||||
show: false
|
||||
};
|
||||
|
||||
private renderMask() {
|
||||
return <Theme
|
||||
className="load-file-layer-root"
|
||||
fontLevel={FontLevel.normal}
|
||||
onDragEnter={this.handleWindowsDragOnFiles}
|
||||
onDragLeave={this.handleWindowsDragOffFiles}
|
||||
>
|
||||
<div className="load-file-layer">
|
||||
<div className="drag-icon">
|
||||
<Icon iconName="KnowledgeArticle"/>
|
||||
</div>
|
||||
<div className="drag-title">
|
||||
<Localization i18nKey="Info.Hint.Load.File.Title"/>
|
||||
</div>
|
||||
<div className="drag-intro">
|
||||
<Localization i18nKey="Info.Hint.Load.File.Intro"/>
|
||||
</div>
|
||||
return <Theme
|
||||
className="load-file-layer-root"
|
||||
fontLevel={FontLevel.normal}
|
||||
>
|
||||
<div className="load-file-layer">
|
||||
<div className="drag-icon">
|
||||
<Icon iconName="KnowledgeArticle"/>
|
||||
</div>
|
||||
</Theme>;
|
||||
}
|
||||
|
||||
private offDragTimer: NodeJS.Timeout | undefined;
|
||||
|
||||
private handleWindowsDragOnFiles = () => {
|
||||
clearTimeout(this.offDragTimer as number | undefined);
|
||||
this.setState({
|
||||
show: true
|
||||
});
|
||||
}
|
||||
|
||||
private handleWindowsDragOffFiles = () => {
|
||||
clearTimeout(this.offDragTimer as number | undefined);
|
||||
this.offDragTimer = setTimeout(() => {
|
||||
this.setState({
|
||||
show: false
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
window.addEventListener("dragenter", this.handleWindowsDragOnFiles);
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
window.removeEventListener("dragenter", this.handleWindowsDragOnFiles);
|
||||
}
|
||||
|
||||
public render(): ReactNode {
|
||||
return this.state.show ? this.renderMask() : null;
|
||||
}
|
||||
<div className="drag-title">
|
||||
<Localization i18nKey="Info.Hint.Load.File.Title"/>
|
||||
</div>
|
||||
<div className="drag-intro">
|
||||
<Localization i18nKey="Info.Hint.Load.File.Intro"/>
|
||||
</div>
|
||||
</div>
|
||||
</Theme>;
|
||||
}
|
||||
|
||||
async function fileChecker(status: Status, file?: File) {
|
||||
|
||||
if (!status) return undefined;
|
||||
|
||||
return new Promise((r, j) => {
|
||||
|
||||
// 检查文件存在性
|
||||
if (!file) {
|
||||
status.popup.showPopup(ConfirmPopup, {
|
||||
infoI18n: "Popup.Load.Save.Error.Empty",
|
||||
titleI18N: "Popup.Load.Save.Title",
|
||||
yesI18n: "Popup.Load.Save.confirm"
|
||||
});
|
||||
return j();
|
||||
}
|
||||
|
||||
// 检测拓展名
|
||||
let extendName = (file.name.match(/\.(\w+)$/) ?? [])[1];
|
||||
if (extendName !== "ltss") {
|
||||
status.popup.showPopup(ConfirmPopup, {
|
||||
infoI18n: "Popup.Load.Save.Error.Type",
|
||||
infoI18nOption: { ext: extendName },
|
||||
titleI18N: "Popup.Load.Save.Title",
|
||||
yesI18n: "Popup.Load.Save.confirm"
|
||||
});
|
||||
return j();
|
||||
}
|
||||
|
||||
// 文件读取
|
||||
let fileReader = new FileReader();
|
||||
fileReader.readAsText(file);
|
||||
fileReader.onload = () => {
|
||||
|
||||
const loadFunc = () => {
|
||||
|
||||
// 进行转换
|
||||
let errorMessage = status.archive.load(status.model, fileReader.result as string, file.name);
|
||||
if (errorMessage) {
|
||||
status.popup.showPopup(ConfirmPopup, {
|
||||
infoI18n: "Popup.Load.Save.Error.Parse",
|
||||
infoI18nOption: { why: errorMessage },
|
||||
titleI18N: "Popup.Load.Save.Title",
|
||||
yesI18n: "Popup.Load.Save.confirm"
|
||||
});
|
||||
j();
|
||||
}
|
||||
|
||||
else {
|
||||
r(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果保存进行提示
|
||||
if (!status.archive.isSaved) {
|
||||
status.popup.showPopup(ConfirmPopup, {
|
||||
infoI18n: "Popup.Load.Save.Overwrite.Info",
|
||||
titleI18N: "Popup.Load.Save.Title",
|
||||
yesI18n: "Popup.Load.Save.Overwrite",
|
||||
noI18n: "Popup.Action.No",
|
||||
red: "yes",
|
||||
yes: () => {
|
||||
loadFunc();
|
||||
},
|
||||
no: () => {
|
||||
j();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
else {
|
||||
loadFunc();
|
||||
}
|
||||
}
|
||||
fileReader.onerror = () => {
|
||||
status.popup.showPopup(ConfirmPopup, {
|
||||
infoI18n: "Popup.Load.Save.Error.Parse",
|
||||
infoI18nOption: { why: "Unknown error" },
|
||||
titleI18N: "Popup.Load.Save.Title",
|
||||
yesI18n: "Popup.Load.Save.confirm"
|
||||
});
|
||||
j();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const LoadFileView: FunctionComponent<IMixinStatusProps> = (props) => {
|
||||
|
||||
const [{ isOver }, drop] = useDrop(() => ({
|
||||
accept: NativeTypes.FILE,
|
||||
drop: (item: { files: File[] }) => {
|
||||
if (props.status) {
|
||||
fileChecker(props.status, item.files[0]).catch((e) => undefined);
|
||||
}
|
||||
},
|
||||
collect: (monitor) => ({
|
||||
isOver: monitor.isOver()
|
||||
})
|
||||
}));
|
||||
|
||||
return <>
|
||||
{
|
||||
isOver ? <DragFileMask/> : null
|
||||
}
|
||||
<div className="load-file-app-root" ref={drop}>
|
||||
{props.children}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
const LoadFile = useStatus(LoadFileView);
|
||||
|
||||
export { LoadFile };
|
||||
Reference in New Issue
Block a user