slate/components/core/ApplicationUserControls.js

300 lines
8.5 KiB
JavaScript
Raw Normal View History

import * as React from "react";
import * as Constants from "~/common/constants";
2021-05-06 03:08:14 +03:00
import * as Styles from "~/common/styles";
import * as UserBehaviors from "~/common/user-behaviors";
import * as Strings from "~/common/strings";
import * as Environment from "~/common/environment";
import * as Utilities from "~/common/utilities";
import { ButtonPrimaryFull, PopoverNavigation } from "~/components/system";
2020-11-30 08:24:22 +03:00
import { css } from "@emotion/react";
2021-05-06 03:08:14 +03:00
import { Link } from "~/components/core/Link";
2020-09-05 00:37:50 +03:00
import { Boundary } from "~/components/system/components/fragments/Boundary";
import { H4, P3 } from "~/components/system/components/Typography";
import ProfilePhoto from "~/components/core/ProfilePhoto";
import DataMeter from "~/components/core/DataMeter";
const STYLES_HEADER = css`
position: relative;
@media (max-width: ${Constants.sizes.mobile}px) {
2020-09-29 07:39:05 +03:00
padding: 0px;
2020-09-29 08:47:27 +03:00
width: auto;
}
`;
const STYLES_PROFILE_MOBILE = css`
display: flex;
2020-09-05 04:40:23 +03:00
align-items: center;
`;
const STYLES_POPOVER_CONTANIER = (theme) => css`
2021-11-10 02:26:13 +03:00
padding: 20px;
border-radius: 16px;
2021-11-12 03:02:32 +03:00
border: 1px solid ${theme.semantic.borderGrayLight};
box-shadow: ${theme.shadow.lightLarge};
@supports ((-webkit-backdrop-filter: blur(75px)) or (backdrop-filter: blur(75px))) {
background-color: ${theme.semantic.bgBlurWhite};
-webkit-backdrop-filter: blur(75px);
backdrop-filter: blur(75px);
}
2021-11-10 02:26:13 +03:00
@media (max-width: ${theme.sizes.mobile}px) {
padding: 16px;
}
`;
const STYLES_POPOVER_SECTION = (theme) => css`
border-top: 1px solid ${theme.semantic.borderGrayLight4};
border-bottom: none;
2021-11-10 02:26:13 +03:00
padding: 8px 0;
margin: 0;
p {
display: block;
width: 100%;
}
:last-child {
padding-bottom: 0px;
}
2020-09-05 22:27:41 +03:00
`;
const STYLES_POPOVER_SECTION_ITEM = (theme) => css`
position: relative;
width: calc(100% + 16px);
left: -8px;
a {
display: block;
}
2021-11-10 02:26:13 +03:00
@media (max-width: ${Constants.sizes.mobile}px) {
margin: 8px 0;
}
`;
const STYLES_SECTION_ITEM_HOVER = (theme) => css`
2021-11-10 02:26:13 +03:00
padding: 5px 8px 7px;
border-radius: 8px;
&:hover {
2021-11-10 02:26:13 +03:00
background-color: ${theme.semantic.bgGrayLight};
}
`;
2021-05-06 03:08:14 +03:00
export class ApplicationUserControlsPopup extends React.Component {
state = {
isExtensionDownloaded: false,
};
componentDidMount() {
if (document) {
const isExtensionDownloaded = this._checkIfExtensionIsDownloaded();
this.setState({ isExtensionDownloaded });
}
}
_checkIfExtensionIsDownloaded = () => {
const extensionElement = document.getElementById("browser_extension");
if (!extensionElement) return false;
return extensionElement.className.includes("isDownloaded");
};
_handleExtensionDownloadLink = () => {
const testUserAgent = (regex) => regex.test(window.navigator.userAgent);
const isFirefox = testUserAgent(/firefox/i);
const firefoxLink = Environment.EXTENSION_FIREFOX;
if (isFirefox && firefoxLink) return window.open(firefoxLink, "_blank");
const isSafari = testUserAgent(/safari/i);
const safariLink = Environment.EXTENSION_SAFARI;
if (isSafari && safariLink) return window.open(safariLink, "_blank");
window.open(Environment.EXTENSION_CHROME, "_blank");
};
2021-05-06 03:08:14 +03:00
_handleAction = (props) => {
this.props.onTogglePopup();
2021-05-06 03:08:14 +03:00
this.props.onAction(props);
};
_handleSignOut = (e) => {
e.preventDefault();
e.stopPropagation();
this.props.onTogglePopup();
2021-04-07 01:08:42 +03:00
UserBehaviors.signOut({ viewer: this.props.viewer });
};
render() {
if (this.props.popup !== "profile") return null;
const username = Utilities.getUserDisplayName(this.props.viewer);
const objectsLength = this.props.viewer.library.length;
const { stats } = this.props.viewer;
const topSection = (
<Link href="/_/data" onAction={this._handleAction}>
<div style={{ marginBottom: 16 }} css={Styles.VERTICAL_CONTAINER_CENTERED}>
<ProfilePhoto user={this.props.viewer} style={{ borderRadius: "12px" }} size={48} />
<H4 color="textBlack" style={{ marginTop: 10 }}>
{username}
</H4>
<div style={{ marginTop: 6 }} css={Styles.HORIZONTAL_CONTAINER}>
<P3 color="textBlack" style={{ marginRight: 8 }}>
{objectsLength} {Strings.pluralize("Object", objectsLength)}
</P3>
<P3 color="textBlack" style={{ marginLeft: 8 }}>
{Strings.bytesToSize(stats.bytes, 0)} of {Strings.bytesToSize(stats.maximumBytes, 0)}{" "}
Stored
</P3>
</div>
<DataMeter
bytes={stats.bytes}
maximumBytes={stats.maximumBytes}
style={{ minWidth: "240px", marginTop: 8 }}
/>
2020-11-14 02:43:59 +03:00
</div>
</Link>
);
2021-05-06 03:08:14 +03:00
const ExtensionButton = (
<div css={Styles.MOBILE_HIDDEN}>
<ButtonPrimaryFull
style={{
2021-11-10 02:26:13 +03:00
padding: "5px 24px 7px",
2021-11-12 01:28:15 +03:00
marginTop: "8px",
}}
onClick={this._handleExtensionDownloadLink}
>
Install Slate browser extension
</ButtonPrimaryFull>
</div>
);
const navigation = [
[
{
text: (
<div css={STYLES_SECTION_ITEM_HOVER}>
<Link href={`/$/user/${this.props.viewer.id}`} onAction={this._handleAction}>
Profile
</Link>
</div>
),
},
{
text: (
<div css={STYLES_SECTION_ITEM_HOVER}>
<Link href={"/_/directory"} onAction={this._handleAction}>
Directory
</Link>
</div>
),
},
],
[
{
text: (
<div css={STYLES_SECTION_ITEM_HOVER}>
<Link href={"/_/api"} onAction={this._handleAction}>
API
</Link>
</div>
),
},
],
[
{
text: (
<div css={STYLES_SECTION_ITEM_HOVER}>
<Link href={"/_/settings"} onAction={this._handleAction}>
Settings
</Link>
</div>
),
},
{
text: <div css={STYLES_SECTION_ITEM_HOVER}> Sign out</div>,
onClick: (e) => {
this._handleSignOut(e);
2021-05-06 03:08:14 +03:00
},
},
...(!this.state.isExtensionDownloaded ? [{ text: ExtensionButton }] : []),
],
];
2021-05-06 03:08:14 +03:00
return (
<>
<div css={Styles.MOBILE_ONLY}>
<Boundary
captureResize={true}
captureScroll={false}
enabled={this.props.popup === "profile"}
onOutsideRectEvent={() => this.props.onTogglePopup()}
>
<PopoverNavigation
style={{
position: "relative",
border: "none",
boxShadow: "none",
background: "none",
pointerEvents: "auto",
}}
containerCss={STYLES_POPOVER_CONTANIER}
sectionCss={STYLES_POPOVER_SECTION}
sectionItemCss={STYLES_POPOVER_SECTION_ITEM}
css={Styles.H4}
itemStyle={{ fontSize: Constants.typescale.lvl0 }}
topSection={topSection}
navigation={navigation}
/>
</Boundary>
</div>
<div css={Styles.MOBILE_HIDDEN}>
<Boundary
captureResize={true}
captureScroll={false}
enabled={this.props.popup === "profile"}
onOutsideRectEvent={() => this.props.onTogglePopup()}
>
<PopoverNavigation
style={{
top: 34,
left: "-12px",
width: "max-content",
}}
containerCss={STYLES_POPOVER_CONTANIER}
sectionCss={STYLES_POPOVER_SECTION}
sectionItemCss={STYLES_POPOVER_SECTION_ITEM}
css={Styles.H4}
itemStyle={{ fontSize: Constants.typescale.lvl0 }}
topSection={topSection}
navigation={navigation}
/>
</Boundary>
</div>
</>
);
2021-05-06 03:08:14 +03:00
}
}
export class ApplicationUserControls extends React.Component {
render() {
let tooltip = <ApplicationUserControlsPopup {...this.props} />;
return (
<div css={STYLES_HEADER}>
<button
css={[Styles.BUTTON_RESET, STYLES_PROFILE_MOBILE]}
2021-08-05 01:56:58 +03:00
onClick={() => this.props.onTogglePopup("profile")}
style={{ position: "relative", cursor: "pointer" }}
>
<ProfilePhoto user={this.props.viewer} style={{ borderRadius: "8px" }} size={24} />
</button>
{this.props.popup === "profile" ? tooltip : null}
</div>
);
}
}