feat(topbar, sharings): introduce qrcode for sharing dirs and site address
This commit is contained in:
parent
1ff7cfc141
commit
e019eb7293
7 changed files with 132 additions and 19 deletions
|
@ -22,6 +22,8 @@
|
||||||
color: #16a085;
|
color: #16a085;
|
||||||
padding: 1rem 2rem 1rem 2rem;
|
padding: 1rem 2rem 1rem 2rem;
|
||||||
-webkit-backdrop-filter: blur(9.5px);
|
-webkit-backdrop-filter: blur(9.5px);
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-default #topbar-user-info {
|
.theme-default #topbar-user-info {
|
||||||
|
@ -40,6 +42,8 @@
|
||||||
color: #16a085;
|
color: #16a085;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
-webkit-backdrop-filter: blur(9.5px);
|
-webkit-backdrop-filter: blur(9.5px);
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-default #top-menu button {
|
.theme-default #top-menu button {
|
||||||
|
@ -217,6 +221,26 @@
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
background-color: #ecf0f1;
|
background-color: #ecf0f1;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
box-shadow: 0 5px 30px 0 rgb(31 38 135 / 10%);
|
||||||
|
backdrop-filter: blur(9.5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-default .qrcode-container {
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-default .qrcode-icon {
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-default .qrcode-child-container {
|
||||||
|
position: relative;
|
||||||
|
z-index: 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-default .qrcode-child {
|
||||||
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-default .item-cell {
|
.theme-default .item-cell {
|
||||||
|
@ -463,11 +487,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-default #login-layer {
|
.theme-default #login-layer {
|
||||||
z-index: 100;
|
z-index: 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-default #settings-layer {
|
.theme-default #settings-layer {
|
||||||
z-index: 1;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-default .value {
|
.theme-default .value {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { RiArchiveDrawerFill } from "@react-icons/all-files/ri/RiArchiveDrawerFi
|
||||||
import { RiFile2Fill } from "@react-icons/all-files/ri/RiFile2Fill";
|
import { RiFile2Fill } from "@react-icons/all-files/ri/RiFile2Fill";
|
||||||
import { RiFileList2Fill } from "@react-icons/all-files/ri/RiFileList2Fill";
|
import { RiFileList2Fill } from "@react-icons/all-files/ri/RiFileList2Fill";
|
||||||
import { RiCheckboxFill } from "@react-icons/all-files/ri/RiCheckboxFill";
|
import { RiCheckboxFill } from "@react-icons/all-files/ri/RiCheckboxFill";
|
||||||
import { RiInformationFill } from "@react-icons/all-files/ri/RiInformationFill";
|
import { RiMore2Fill } from "@react-icons/all-files/ri/RiMore2Fill";
|
||||||
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 { RiRefreshLine } from "@react-icons/all-files/ri/RiRefreshLine";
|
||||||
|
@ -499,7 +499,7 @@ export class FilesPanel extends React.Component<Props, State, {}> {
|
||||||
onClick={() => this.toggleDetail(item.name)}
|
onClick={() => this.toggleDetail(item.name)}
|
||||||
className="float-l"
|
className="float-l"
|
||||||
>
|
>
|
||||||
{getIcon("RiInformationFill", "1.8rem", detailColor)}
|
{getIcon("RiMore2Fill", "1.8rem", detailColor)}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span onClick={() => this.select(item.name)} className="float-l">
|
<span onClick={() => this.select(item.name)} className="float-l">
|
||||||
|
@ -605,7 +605,7 @@ export class FilesPanel extends React.Component<Props, State, {}> {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={`v-mid item-op ${showOp}`}>
|
<div className={`v-mid item-op ${showOp}`}>
|
||||||
<RiInformationFill
|
<RiMore2Fill
|
||||||
size="1.8rem"
|
size="1.8rem"
|
||||||
className={`${descIconColor} margin-r-m`}
|
className={`${descIconColor} margin-r-m`}
|
||||||
onClick={() => this.toggleDetail(item.name)}
|
onClick={() => this.toggleDetail(item.name)}
|
||||||
|
@ -626,15 +626,22 @@ export class FilesPanel extends React.Component<Props, State, {}> {
|
||||||
const fileTypeTitle = this.props.msg.pkg.get("item.type");
|
const fileTypeTitle = this.props.msg.pkg.get("item.type");
|
||||||
const itemSize = FileSize(item.size, { round: 0 });
|
const itemSize = FileSize(item.size, { round: 0 });
|
||||||
|
|
||||||
const compact = item.isDir
|
const compact = item.isDir ? (
|
||||||
? `${pathTitle}: ${itemPath} | ${modTimeTitle}: ${item.modTime}`
|
<span>
|
||||||
: `${pathTitle}: ${itemPath} | ${modTimeTitle}: ${item.modTime} | ${sizeTitle}: ${itemSize} | sha1: ${item.sha1}`;
|
<span className="grey3-font">{`${pathTitle}: `}</span>
|
||||||
|
<span>{`${absDownloadURL} | `}</span>
|
||||||
|
<span className="grey3-font">{`${modTimeTitle}: `}</span>
|
||||||
|
<span>{item.modTime}</span>
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
`${pathTitle}: ${absDownloadURL} | ${modTimeTitle}: ${item.modTime} | ${sizeTitle}: ${itemSize} | sha1: ${item.sha1}`
|
||||||
|
);
|
||||||
const details = (
|
const details = (
|
||||||
<div>
|
<div>
|
||||||
<div className="column">
|
<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>{absDownloadURL}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<span className="title-m black-font">{modTimeTitle}</span>
|
<span className="title-m black-font">{modTimeTitle}</span>
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { List } from "immutable";
|
import { List } from "immutable";
|
||||||
|
import QRCode from "react-qr-code";
|
||||||
|
|
||||||
import { RiShareBoxLine } from "@react-icons/all-files/ri/RiShareBoxLine";
|
import { RiShareBoxLine } from "@react-icons/all-files/ri/RiShareBoxLine";
|
||||||
import { RiFolderSharedFill } from "@react-icons/all-files/ri/RiFolderSharedFill";
|
import { RiFolderSharedFill } from "@react-icons/all-files/ri/RiFolderSharedFill";
|
||||||
import { RiEmotionSadLine } from "@react-icons/all-files/ri/RiEmotionSadLine";
|
import { RiEmotionSadLine } from "@react-icons/all-files/ri/RiEmotionSadLine";
|
||||||
|
|
||||||
|
import { QRCodeIcon } from "./visual/qrcode";
|
||||||
import { getErrMsg } from "../common/utils";
|
import { getErrMsg } from "../common/utils";
|
||||||
import { alertMsg, confirmMsg } from "../common/env";
|
import { alertMsg, confirmMsg } from "../common/env";
|
||||||
import { updater } from "./state_updater";
|
import { updater } from "./state_updater";
|
||||||
|
@ -68,13 +70,26 @@ export class SharingsPanel extends React.Component<Props, State, {}> {
|
||||||
<div className="info">{dirPath}</div>
|
<div className="info">{dirPath}</div>
|
||||||
|
|
||||||
<div className="op">
|
<div className="op">
|
||||||
|
<Flexbox
|
||||||
|
children={List([
|
||||||
|
<span className="margin-r-m">
|
||||||
|
<QRCodeIcon value={sharingURL} size={128} pos={false} />
|
||||||
|
</span>,
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.deleteSharing(dirPath);
|
this.deleteSharing(dirPath);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{this.props.msg.pkg.get("browser.delete")}
|
{this.props.msg.pkg.get("browser.delete")}
|
||||||
</button>
|
</button>,
|
||||||
|
])}
|
||||||
|
childrenStyles={List([
|
||||||
|
{ flex: "0 0 auto" },
|
||||||
|
{ flex: "0 0 auto" },
|
||||||
|
])}
|
||||||
|
style={{ justifyContent: "flex-end" }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -83,7 +98,7 @@ export class SharingsPanel extends React.Component<Props, State, {}> {
|
||||||
<div className="sharing-item" key={dirPath}>
|
<div className="sharing-item" key={dirPath}>
|
||||||
{row1}
|
{row1}
|
||||||
<div className="desc">{sharingURL}</div>
|
<div className="desc">{sharingURL}</div>
|
||||||
<div className="hr grey0-bg"></div>
|
<div className="hr"></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { LoginProps } from "./pane_login";
|
||||||
import { updater } from "./state_updater";
|
import { updater } from "./state_updater";
|
||||||
import { Flexbox } from "./layout/flexbox";
|
import { Flexbox } from "./layout/flexbox";
|
||||||
import { settingsDialogCtrl } from "./layers";
|
import { settingsDialogCtrl } from "./layers";
|
||||||
|
import { QRCodeIcon } from "./visual/qrcode";
|
||||||
|
|
||||||
export interface State {}
|
export interface State {}
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -90,6 +91,7 @@ export class TopBar extends React.Component<Props, State, {}> {
|
||||||
>
|
>
|
||||||
Quickshare
|
Quickshare
|
||||||
</a>,
|
</a>,
|
||||||
|
<QRCodeIcon value={document.URL} size={128} pos={true} className="margin-l-m"/>,
|
||||||
|
|
||||||
<Flexbox
|
<Flexbox
|
||||||
children={List([
|
children={List([
|
||||||
|
@ -109,7 +111,8 @@ export class TopBar extends React.Component<Props, State, {}> {
|
||||||
/>,
|
/>,
|
||||||
])}
|
])}
|
||||||
childrenStyles={List([
|
childrenStyles={List([
|
||||||
{},
|
{ flex: "0 0 auto" },
|
||||||
|
{ flex: "0 0 auto" },
|
||||||
{ justifyContent: "flex-end", alignItems: "center" },
|
{ justifyContent: "flex-end", alignItems: "center" },
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { RiFileList2Fill } from "@react-icons/all-files/ri/RiFileList2Fill";
|
||||||
import { RiArrowUpDownFill } from "@react-icons/all-files/ri/RiArrowUpDownFill";
|
import { RiArrowUpDownFill } from "@react-icons/all-files/ri/RiArrowUpDownFill";
|
||||||
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 { RiMore2Fill } from "@react-icons/all-files/ri/RiMore2Fill";
|
||||||
|
|
||||||
import { colorClass } from "./colors";
|
import { colorClass } from "./colors";
|
||||||
|
|
||||||
|
@ -42,6 +43,7 @@ const icons = Map<string, IconType>({
|
||||||
RiArrowUpDownFill: RiArrowUpDownFill,
|
RiArrowUpDownFill: RiArrowUpDownFill,
|
||||||
BiTable: BiTable,
|
BiTable: BiTable,
|
||||||
BiListUl: BiListUl,
|
BiListUl: BiListUl,
|
||||||
|
RiMore2Fill: RiMore2Fill,
|
||||||
});
|
});
|
||||||
|
|
||||||
export function getIconWithProps(
|
export function getIconWithProps(
|
||||||
|
|
62
src/client/web/src/components/visual/qrcode.tsx
Normal file
62
src/client/web/src/components/visual/qrcode.tsx
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import QRCode from "react-qr-code";
|
||||||
|
|
||||||
|
import { RiQrCodeFill } from "@react-icons/all-files/ri/RiQrCodeFill";
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
value: string;
|
||||||
|
size: number;
|
||||||
|
pos: boolean; // true=left, right=false
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface State {
|
||||||
|
show: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class QRCodeIcon extends React.Component<Props, State, {}> {
|
||||||
|
constructor(p: Props) {
|
||||||
|
super(p);
|
||||||
|
this.state = {
|
||||||
|
show: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle = () => {
|
||||||
|
this.setState({ show: !this.state.show });
|
||||||
|
};
|
||||||
|
|
||||||
|
show = () => {
|
||||||
|
this.setState({ show: true });
|
||||||
|
};
|
||||||
|
hide = () => {
|
||||||
|
this.setState({ show: false });
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const widthInRem = `${Math.floor(this.props.size / 10)}rem`;
|
||||||
|
const posStyle = this.props.pos
|
||||||
|
? { right: `-${widthInRem}rem` }
|
||||||
|
: { left: `-${widthInRem}rem` };
|
||||||
|
const qrcode = this.state.show ? (
|
||||||
|
<div className="qrcode-child" style={{ ...posStyle }}>
|
||||||
|
<div className="qrcode">
|
||||||
|
<QRCode value={this.props.value} size={this.props.size} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`qrcode-container ${this.props.className}`}>
|
||||||
|
<RiQrCodeFill
|
||||||
|
className="qrcode-icon"
|
||||||
|
onMouseEnter={this.show}
|
||||||
|
onMouseLeave={this.hide}
|
||||||
|
onClick={this.toggle}
|
||||||
|
size={"2rem"}
|
||||||
|
/>
|
||||||
|
<div className="qrcode-child-container">{qrcode}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue