feat(fe/files panel): enable download URL QR code

This commit is contained in:
hexxa 2021-12-30 17:28:06 +08:00 committed by Hexxa
parent f46d492d44
commit 1ff7cfc141
7 changed files with 93 additions and 34 deletions

View file

@ -498,3 +498,7 @@
.bold { .bold {
font-weight: bold; font-weight: bold;
} }
.fix {
clear: both;
}

View file

@ -196,6 +196,29 @@
text-align: left; text-align: left;
} }
.theme-default #item-rows .column {
width: 50%;
max-width: 100%;
float: left;
}
.theme-default #browser .info {
border: dashed 1px #95a5a6;
font-size: 1.4rem;
padding: 1rem;
color: #697384;
margin: 1rem 0 0 0;
background-color: #ecf0f1;
white-space: nowrap;
overflow: auto;
}
.theme-default .qrcode {
padding: 1rem;
background-color: #ecf0f1;
display: inline-block;
}
.theme-default .item-cell { .theme-default .item-cell {
height: 5rem; height: 5rem;
} }

View file

@ -58,6 +58,7 @@
"react-copy-to-clipboard": "^5.0.1", "react-copy-to-clipboard": "^5.0.1",
"react-dom": "^16.8.6", "react-dom": "^16.8.6",
"react-icons": "4.3.1", "react-icons": "4.3.1",
"react-qr-code": "^2.0.3",
"react-svg": "^8.0.6", "react-svg": "^8.0.6",
"throttle-debounce": "^2.1.0", "throttle-debounce": "^2.1.0",
"webpack-bundle-analyzer": "^4.4.2", "webpack-bundle-analyzer": "^4.4.2",

View file

@ -2,6 +2,7 @@ import * as React from "react";
import * as ReactDOM from "react-dom"; import * as ReactDOM from "react-dom";
import { List, Map, Set } from "immutable"; import { List, Map, Set } from "immutable";
import FileSize from "filesize"; import FileSize from "filesize";
import QRCode from "react-qr-code";
import { RiFolder2Fill } from "@react-icons/all-files/ri/RiFolder2Fill"; import { RiFolder2Fill } from "@react-icons/all-files/ri/RiFolder2Fill";
import { RiArchiveDrawerFill } from "@react-icons/all-files/ri/RiArchiveDrawerFill"; import { RiArchiveDrawerFill } from "@react-icons/all-files/ri/RiArchiveDrawerFill";
@ -11,6 +12,7 @@ import { RiCheckboxFill } from "@react-icons/all-files/ri/RiCheckboxFill";
import { RiInformationFill } from "@react-icons/all-files/ri/RiInformationFill"; import { RiInformationFill } from "@react-icons/all-files/ri/RiInformationFill";
import { BiTable } from "@react-icons/all-files/bi/BiTable"; import { BiTable } from "@react-icons/all-files/bi/BiTable";
import { BiListUl } from "@react-icons/all-files/bi/BiListUl"; import { BiListUl } from "@react-icons/all-files/bi/BiListUl";
import { RiRefreshLine } from "@react-icons/all-files/ri/RiRefreshLine";
import { ErrorLogger } from "../common/log_error"; import { ErrorLogger } from "../common/log_error";
import { alertMsg, confirmMsg } from "../common/env"; import { alertMsg, confirmMsg } from "../common/env";
@ -465,17 +467,17 @@ export class FilesPanel extends React.Component<Props, State, {}> {
> >
<Flexbox <Flexbox
children={List([ children={List([
<span> <div className="label">{`SHA1: `}</div>,
<div className="label">{`SHA1: `}</div> <RiRefreshLine
<input type="text" readOnly={true} value={`${item.sha1}`} /> onClick={() => this.generateHash(itemPath)}
</span>, size={"2rem"}
<button onClick={() => this.generateHash(itemPath)}> className="black-font"
{this.props.msg.pkg.get("refresh")} />,
</button>,
])} ])}
className="item-info" className="item-info"
childrenStyles={List([{}, { justifyContent: "flex-end" }])} childrenStyles={List([{}, { justifyContent: "flex-end" }])}
/> />
<div className="info">{item.sha1}</div>
</div> </div>
</div> </div>
); );
@ -582,16 +584,13 @@ export class FilesPanel extends React.Component<Props, State, {}> {
? this.props.msg.pkg.get("item.type.folder") ? this.props.msg.pkg.get("item.type.folder")
: this.props.msg.pkg.get("item.type.file"); : this.props.msg.pkg.get("item.type.file");
const downloadPath = `/v1/fs/files?fp=${itemPath}`;
const name = item.isDir ? ( const name = item.isDir ? (
<span className="clickable" onClick={() => this.gotoChild(item.name)}> <span className="clickable" onClick={() => this.gotoChild(item.name)}>
{item.name} {item.name}
</span> </span>
) : ( ) : (
<a <a className="title-m clickable" href={downloadPath} target="_blank">
className="title-m clickable"
href={`/v1/fs/files?fp=${itemPath}`}
target="_blank"
>
{item.name} {item.name}
</a> </a>
); );
@ -620,7 +619,8 @@ export class FilesPanel extends React.Component<Props, State, {}> {
</div> </div>
); );
const pathTitle = this.props.msg.pkg.get("item.path"); const absDownloadURL = `${document.location.protocol}//${document.location.hostname}${downloadPath}`;
const pathTitle = this.props.msg.pkg.get("item.downloadURL");
const modTimeTitle = this.props.msg.pkg.get("item.modTime"); const modTimeTitle = this.props.msg.pkg.get("item.modTime");
const sizeTitle = this.props.msg.pkg.get("item.size"); const sizeTitle = this.props.msg.pkg.get("item.size");
const fileTypeTitle = this.props.msg.pkg.get("item.type"); const fileTypeTitle = this.props.msg.pkg.get("item.type");
@ -631,6 +631,7 @@ export class FilesPanel extends React.Component<Props, State, {}> {
: `${pathTitle}: ${itemPath} | ${modTimeTitle}: ${item.modTime} | ${sizeTitle}: ${itemSize} | sha1: ${item.sha1}`; : `${pathTitle}: ${itemPath} | ${modTimeTitle}: ${item.modTime} | ${sizeTitle}: ${itemSize} | sha1: ${item.sha1}`;
const details = ( const details = (
<div> <div>
<div className="column">
<div className="card"> <div className="card">
<span className="title-m black-font">{pathTitle}</span> <span className="title-m black-font">{pathTitle}</span>
<span>{itemPath}</span> <span>{itemPath}</span>
@ -643,17 +644,32 @@ export class FilesPanel extends React.Component<Props, State, {}> {
<span className="title-m black-font">{sizeTitle}</span> <span className="title-m black-font">{sizeTitle}</span>
<span>{itemSize}</span> <span>{itemSize}</span>
</div> </div>
</div>
<div className="column">
<div className="card">
<span className="title-m black-font">{pathTitle}</span>
<div className="qrcode">
<QRCode value={absDownloadURL} size={128} />
</div>
</div>
</div>
<div className="fix">
<div className="card"> <div className="card">
<span className="title-m black-font">SHA1</span>
<Flexbox <Flexbox
children={List([ children={List([
<input type="text" readOnly={true} value={`${item.sha1}`} />, <span className="title-m black-font">SHA1</span>,
<button onClick={() => this.generateHash(itemPath)}> <RiRefreshLine
{this.props.msg.pkg.get("refresh")} onClick={() => this.generateHash(itemPath)}
</button>, size={"2rem"}
className="black-font"
/>,
])} ])}
childrenStyles={List([{}, { justifyContent: "flex-end" }])} childrenStyles={List([{}, { justifyContent: "flex-end" }])}
/> />
<div className="info">{item.sha1}</div>
</div>
</div> </div>
</div> </div>
); );

View file

@ -126,6 +126,7 @@ export const msgs: Map<string, string> = Map({
"item.modTime": "Mod Time", "item.modTime": "Mod Time",
"item.size": "Size", "item.size": "Size",
"item.progress": "Progress", "item.progress": "Progress",
"item.downloadURL": "Download URL",
"error.report.title": "Error Report", "error.report.title": "Error Report",
"op.truncate": "Truncate", "op.truncate": "Truncate",
"op.submit": "Submit", "op.submit": "Submit",

View file

@ -123,6 +123,7 @@ export const msgs: Map<string, string> = Map({
"item.modTime": "修改时间", "item.modTime": "修改时间",
"item.size": "大小", "item.size": "大小",
"item.progress": "进度", "item.progress": "进度",
"item.downloadURL": "下载链接",
"error.report.title": "报告错误", "error.report.title": "报告错误",
"op.truncate": "清空", "op.truncate": "清空",
"op.submit": "提交", "op.submit": "提交",

View file

@ -4047,6 +4047,11 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
qr.js@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=
randombytes@^2.1.0: randombytes@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@ -4087,6 +4092,14 @@ react-is@^17.0.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
react-qr-code@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/react-qr-code/-/react-qr-code-2.0.3.tgz#cc80785e08f817d1ab066ca4035262f77d049648"
integrity sha512-6GDH0l53lksf2JgZwwcoS0D60a1OAal/GQRyNFkMBW19HjSqvtD5S20scmSQsKl+BgWM85Wd5DCcUYoHd+PZnQ==
dependencies:
prop-types "^15.7.2"
qr.js "0.0.0"
react-svg@*: react-svg@*:
version "14.0.13" version "14.0.13"
resolved "https://registry.yarnpkg.com/react-svg/-/react-svg-14.0.13.tgz#fd458d52884efcd8c8a6fb2dc20cc7c603b64b45" resolved "https://registry.yarnpkg.com/react-svg/-/react-svg-14.0.13.tgz#fd458d52884efcd8c8a6fb2dc20cc7c603b64b45"