mirror of
https://github.com/filecoin-project/slate.git
synced 2024-12-23 09:01:56 +03:00
mobile refactor
This commit is contained in:
parent
9e12cb402a
commit
bf079ffc8a
@ -51,6 +51,12 @@ const REJECT_LIST = [
|
|||||||
"data",
|
"data",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const onMobile = () => {
|
||||||
|
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
||||||
|
navigator.userAgent
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const userRoute = (text) => {
|
export const userRoute = (text) => {
|
||||||
if (!USERNAME_REGEX.test(text)) {
|
if (!USERNAME_REGEX.test(text)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -19,13 +19,14 @@ const STYLES_ALERT = `
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
transition: top 0.25s;
|
||||||
|
|
||||||
@media (max-width: ${Constants.sizes.mobile}px) {
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
top: 56px;
|
|
||||||
left: 0px;
|
left: 0px;
|
||||||
right: 0px;
|
right: 0px;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -139,7 +140,7 @@ export class Alert extends React.Component {
|
|||||||
// NOTE(jim): Replaces the filecoin banner on some navigation pages.
|
// NOTE(jim): Replaces the filecoin banner on some navigation pages.
|
||||||
if (this.props.filecoin) {
|
if (this.props.filecoin) {
|
||||||
return (
|
return (
|
||||||
<div css={STYLES_MESSAGE}>
|
<div css={STYLES_MESSAGE} style={this.props.style}>
|
||||||
<div css={STYLES_MESSAGE_BOX} style={{ fontSize: 14 }}>
|
<div css={STYLES_MESSAGE_BOX} style={{ fontSize: 14 }}>
|
||||||
You are on the Filecoin Testnet. Test FIL may take a moment to
|
You are on the Filecoin Testnet. Test FIL may take a moment to
|
||||||
reach your wallet.
|
reach your wallet.
|
||||||
@ -149,7 +150,7 @@ export class Alert extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div css={STYLES_MESSAGE}>
|
<div css={STYLES_MESSAGE} style={this.props.style}>
|
||||||
<div css={STYLES_MESSAGE_BOX} style={{ fontSize: 14 }}>
|
<div css={STYLES_MESSAGE_BOX} style={{ fontSize: 14 }}>
|
||||||
Please don't upload sensitive information to Slate yet. Private
|
Please don't upload sensitive information to Slate yet. Private
|
||||||
storage is coming soon.
|
storage is coming soon.
|
||||||
@ -165,7 +166,7 @@ export class Alert extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
css={STYLES_INFO}
|
css={STYLES_INFO}
|
||||||
style={{ cursor: "pointer" }}
|
style={{ cursor: "pointer", ...this.props.style }}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
this.props.onAction({
|
this.props.onAction({
|
||||||
type: "SIDEBAR",
|
type: "SIDEBAR",
|
||||||
|
@ -700,6 +700,7 @@ export default class ApplicationPage extends React.Component {
|
|||||||
<SceneSignIn
|
<SceneSignIn
|
||||||
onCreateUser={this._handleCreateUser}
|
onCreateUser={this._handleCreateUser}
|
||||||
onAuthenticate={this._handleAuthenticate}
|
onAuthenticate={this._handleAuthenticate}
|
||||||
|
onAction={this._handleAction}
|
||||||
/>
|
/>
|
||||||
</WebsitePrototypeWrapper>
|
</WebsitePrototypeWrapper>
|
||||||
);
|
);
|
||||||
|
@ -160,6 +160,8 @@ export default class ApplicationHeader extends React.Component {
|
|||||||
style={{ transform: `rotate(180deg)` }}
|
style={{ transform: `rotate(180deg)` }}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
</span>
|
||||||
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
<span
|
<span
|
||||||
css={STYLES_ICON_ELEMENT}
|
css={STYLES_ICON_ELEMENT}
|
||||||
style={
|
style={
|
||||||
@ -171,7 +173,8 @@ export default class ApplicationHeader extends React.Component {
|
|||||||
>
|
>
|
||||||
<SVG.NavigationArrow height="24px" />
|
<SVG.NavigationArrow height="24px" />
|
||||||
</span>
|
</span>
|
||||||
|
</span>
|
||||||
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
<span
|
<span
|
||||||
css={this.state.isRefreshing ? STYLES_ROTATION : STYLES_STATIC}
|
css={this.state.isRefreshing ? STYLES_ROTATION : STYLES_STATIC}
|
||||||
style={{ marginLeft: 24 }}
|
style={{ marginLeft: 24 }}
|
||||||
@ -180,7 +183,8 @@ export default class ApplicationHeader extends React.Component {
|
|||||||
<SVG.Refresh height="20px" />
|
<SVG.Refresh height="20px" />
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
</span>
|
||||||
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
<span
|
<span
|
||||||
css={STYLES_ICON_ELEMENT}
|
css={STYLES_ICON_ELEMENT}
|
||||||
style={{ marginLeft: 24 }}
|
style={{ marginLeft: 24 }}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as Constants from "~/common/constants";
|
import * as Constants from "~/common/constants";
|
||||||
import * as SVG from "~/common/svg";
|
import * as SVG from "~/common/svg";
|
||||||
|
import * as Validations from "~/common/validations";
|
||||||
|
|
||||||
import { css } from "@emotion/react";
|
import { css } from "@emotion/react";
|
||||||
import { GlobalTooltip } from "~/components/system/components/fragments/GlobalTooltip";
|
import { GlobalTooltip } from "~/components/system/components/fragments/GlobalTooltip";
|
||||||
@ -51,6 +52,7 @@ const STYLES_HEADER = css`
|
|||||||
left: ${Constants.sizes.navigation}px;
|
left: ${Constants.sizes.navigation}px;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
transition: top 0.25s;
|
||||||
@media (max-width: ${Constants.sizes.mobile}px) {
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
@ -163,11 +165,59 @@ const STYLES_BLOCK = css`
|
|||||||
color: rgba(0, 0, 0, 0.25);
|
color: rgba(0, 0, 0, 0.25);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const STYLES_MOBILE_HIDDEN = css`
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_MOBILE_ONLY = css`
|
||||||
|
@media (min-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export default class ApplicationLayout extends React.Component {
|
export default class ApplicationLayout extends React.Component {
|
||||||
_sidebar;
|
_sidebar;
|
||||||
_navigation;
|
_navigation;
|
||||||
_body;
|
_body;
|
||||||
|
|
||||||
|
state = {
|
||||||
|
alertTop: 56,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount = () => {
|
||||||
|
this.prevScrollPos = window.pageYOffset;
|
||||||
|
if (Validations.onMobile()) {
|
||||||
|
window.addEventListener("scroll", this._handleScroll);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillUnmount = () => {
|
||||||
|
if (Validations.onMobile()) {
|
||||||
|
window.removeEventListener("scroll", this._handleScroll);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_handleScroll = () => {
|
||||||
|
console.log(document.getElementById("slate-mobile-alert"));
|
||||||
|
let currentScrollPos = window.pageYOffset;
|
||||||
|
if (this.prevScrollPos > currentScrollPos) {
|
||||||
|
if (document.getElementById("slate-mobile-header")) {
|
||||||
|
document.getElementById("slate-mobile-header").style.top = "0px";
|
||||||
|
}
|
||||||
|
this.setState({ alertTop: 56 });
|
||||||
|
} else {
|
||||||
|
if (currentScrollPos > 56) {
|
||||||
|
if (document.getElementById("slate-mobile-header")) {
|
||||||
|
document.getElementById("slate-mobile-header").style.top = "-56px";
|
||||||
|
}
|
||||||
|
this.setState({ alertTop: 0 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.prevScrollPos = currentScrollPos;
|
||||||
|
};
|
||||||
|
|
||||||
_handleDismiss = (e) => {
|
_handleDismiss = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -184,11 +234,7 @@ export default class ApplicationLayout extends React.Component {
|
|||||||
allowedTypes={["sidebar"]}
|
allowedTypes={["sidebar"]}
|
||||||
/>
|
/>
|
||||||
<div css={STYLES_SIDEBAR_HEADER}>
|
<div css={STYLES_SIDEBAR_HEADER}>
|
||||||
<div
|
<div css={STYLES_BLOCK} onClick={this._handleDismiss}>
|
||||||
css={STYLES_BLOCK}
|
|
||||||
onMouseUp={this._handleDismiss}
|
|
||||||
onTouchEnd={this._handleDismiss}
|
|
||||||
>
|
|
||||||
<SVG.Dismiss height="24px" />
|
<SVG.Dismiss height="24px" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -212,8 +258,16 @@ export default class ApplicationLayout extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div css={STYLES_CONTENT}>
|
<div css={STYLES_CONTENT}>
|
||||||
<GlobalTooltip elementRef={this._body} allowedTypes={["body"]} />
|
{/* <GlobalTooltip elementRef={this._body} allowedTypes={["body"]} /> */}
|
||||||
<div css={STYLES_HEADER}>{this.props.header}</div>
|
<GlobalTooltip allowedTypes={["body"]} />
|
||||||
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
|
<div css={STYLES_HEADER}>{this.props.header}</div>
|
||||||
|
</span>
|
||||||
|
<span css={STYLES_MOBILE_ONLY}>
|
||||||
|
<div css={STYLES_HEADER} id="slate-mobile-header">
|
||||||
|
{this.props.header}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
<div
|
<div
|
||||||
css={STYLES_BODY_WEB}
|
css={STYLES_BODY_WEB}
|
||||||
ref={(c) => {
|
ref={(c) => {
|
||||||
@ -235,14 +289,10 @@ export default class ApplicationLayout extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
<div css={STYLES_BODY_MOBILE}>
|
<div css={STYLES_BODY_MOBILE}>
|
||||||
<Alert
|
<Alert
|
||||||
|
id="slate-mobile-alert"
|
||||||
fileLoading={this.props.fileLoading}
|
fileLoading={this.props.fileLoading}
|
||||||
onAction={this.props.onAction}
|
onAction={this.props.onAction}
|
||||||
style={{
|
style={{ top: this.state.alertTop }}
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
width: "100%",
|
|
||||||
zIndex: Constants.zindex.modal,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
</div>
|
</div>
|
||||||
|
@ -124,8 +124,7 @@ const Item = (props) => {
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
css={STYLES_EXPANDER}
|
css={STYLES_EXPANDER}
|
||||||
onMouseUp={props.onToggleShow ? props.onToggleShow : null}
|
onClick={props.onToggleShow ? props.onToggleShow : null}
|
||||||
onTouchEnd={props.onToggleShow ? props.onToggleShow : null}
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
css={STYLES_ICON_ELEMENT}
|
css={STYLES_ICON_ELEMENT}
|
||||||
@ -143,14 +142,7 @@ const Item = (props) => {
|
|||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
css={STYLES_ICON}
|
css={STYLES_ICON}
|
||||||
onMouseUp={() =>
|
onClick={() =>
|
||||||
props.onAction({
|
|
||||||
type: "NAVIGATE",
|
|
||||||
value: props.id,
|
|
||||||
data: props.data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onTouchEnd={() =>
|
|
||||||
props.onAction({
|
props.onAction({
|
||||||
type: "NAVIGATE",
|
type: "NAVIGATE",
|
||||||
value: props.id,
|
value: props.id,
|
||||||
@ -169,14 +161,7 @@ const Item = (props) => {
|
|||||||
<span
|
<span
|
||||||
css={STYLES_CHILDREN}
|
css={STYLES_CHILDREN}
|
||||||
children={props.children}
|
children={props.children}
|
||||||
onMouseUp={() =>
|
onClick={() =>
|
||||||
props.onAction({
|
|
||||||
type: "NAVIGATE",
|
|
||||||
value: props.id,
|
|
||||||
data: props.data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onTouchEnd={() =>
|
|
||||||
props.onAction({
|
props.onAction({
|
||||||
type: "NAVIGATE",
|
type: "NAVIGATE",
|
||||||
value: props.id,
|
value: props.id,
|
||||||
@ -267,6 +252,7 @@ export default class ApplicationNavigation extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
key={each.id}
|
||||||
css={
|
css={
|
||||||
each.id === "V1_NAVIGATION_ARCHIVE" ||
|
each.id === "V1_NAVIGATION_ARCHIVE" ||
|
||||||
each.id === "V1_NAVIGATION_API"
|
each.id === "V1_NAVIGATION_API"
|
||||||
|
@ -15,6 +15,10 @@ const STYLES_CONTAINER = css`
|
|||||||
padding: 32px;
|
padding: 32px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_DATA = css`
|
const STYLES_DATA = css`
|
||||||
|
@ -184,6 +184,12 @@ const STYLES_IMAGE_GRID = css`
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(214px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(214px, 1fr));
|
||||||
margin: 0 -27px;
|
margin: 0 -27px;
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
margin: 0px -12px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_IMAGE_BOX = css`
|
const STYLES_IMAGE_BOX = css`
|
||||||
@ -197,6 +203,18 @@ const STYLES_IMAGE_BOX = css`
|
|||||||
0 0 40px 0 ${Constants.system.shadow};
|
0 0 40px 0 ${Constants.system.shadow};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
width: 144px;
|
||||||
|
height: 144px;
|
||||||
|
margin: 12px auto;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_MOBILE_HIDDEN = css`
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const delay = (ms) => new Promise((resolve) => window.setTimeout(resolve, ms));
|
const delay = (ms) => new Promise((resolve) => window.setTimeout(resolve, ms));
|
||||||
@ -601,7 +619,7 @@ export default class DataView extends React.Component {
|
|||||||
const header = (
|
const header = (
|
||||||
<div css={STYLES_HEADER_LINE}>
|
<div css={STYLES_HEADER_LINE}>
|
||||||
<TabGroup disabled tabs={["Uploads"]} style={{ margin: 0 }} />
|
<TabGroup disabled tabs={["Uploads"]} style={{ margin: 0 }} />
|
||||||
<React.Fragment>
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
<div
|
<div
|
||||||
css={STYLES_ICON_BOX}
|
css={STYLES_ICON_BOX}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -634,7 +652,7 @@ export default class DataView extends React.Component {
|
|||||||
height="24px"
|
height="24px"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const footer = (
|
const footer = (
|
||||||
@ -738,104 +756,112 @@ export default class DataView extends React.Component {
|
|||||||
title={each.file || each.name}
|
title={each.file || each.name}
|
||||||
type={each.type || each.icon}
|
type={each.type || each.icon}
|
||||||
/>
|
/>
|
||||||
{numChecked ||
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
this.state.hover === i ||
|
{numChecked ||
|
||||||
this.state.menu === each.id ? (
|
this.state.hover === i ||
|
||||||
<React.Fragment>
|
this.state.menu === each.id ? (
|
||||||
<div
|
<React.Fragment>
|
||||||
css={STYLES_ICON_BOX_BACKGROUND}
|
<div
|
||||||
onClick={
|
css={STYLES_ICON_BOX_BACKGROUND}
|
||||||
this.state.loading[cid]
|
onClick={
|
||||||
? () => {}
|
this.state.loading[cid]
|
||||||
: (e) => {
|
? () => {}
|
||||||
e.stopPropagation();
|
: (e) => {
|
||||||
this.setState({
|
e.stopPropagation();
|
||||||
menu:
|
this.setState({
|
||||||
this.state.menu === each.id
|
menu:
|
||||||
? null
|
this.state.menu === each.id
|
||||||
: each.id,
|
? null
|
||||||
});
|
: each.id,
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
>
|
}
|
||||||
{this.state.loading[cid] ? (
|
>
|
||||||
<LoaderSpinner style={{ height: 24, width: 24 }} />
|
{this.state.loading[cid] ? (
|
||||||
) : (
|
<LoaderSpinner
|
||||||
<SVG.MoreHorizontal height="24px" />
|
style={{ height: 24, width: 24 }}
|
||||||
)}
|
|
||||||
|
|
||||||
{this.state.menu === each.id ? (
|
|
||||||
<Boundary
|
|
||||||
captureResize={true}
|
|
||||||
captureScroll={false}
|
|
||||||
enabled
|
|
||||||
onOutsideRectEvent={this._handleHide}
|
|
||||||
>
|
|
||||||
<PopoverNavigation
|
|
||||||
style={{
|
|
||||||
top: "32px",
|
|
||||||
right: "0px",
|
|
||||||
}}
|
|
||||||
navigation={[
|
|
||||||
{
|
|
||||||
text: "Copy CID",
|
|
||||||
onClick: (e) => this._handleCopy(e, cid),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Copy link",
|
|
||||||
onClick: (e) =>
|
|
||||||
this._handleCopy(
|
|
||||||
e,
|
|
||||||
`${Constants.gateways.ipfs}/${cid}`
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Delete",
|
|
||||||
onClick: (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
this.setState({ menu: null }, () =>
|
|
||||||
this._handleDelete(cid)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
</Boundary>
|
) : (
|
||||||
) : null}
|
<SVG.MoreHorizontal height="24px" />
|
||||||
</div>
|
)}
|
||||||
<div
|
|
||||||
onClick={(e) => {
|
{this.state.menu === each.id ? (
|
||||||
e.stopPropagation();
|
<Boundary
|
||||||
e.preventDefault();
|
captureResize={true}
|
||||||
let checked = this.state.checked;
|
captureScroll={false}
|
||||||
if (checked[this.state.startIndex + i]) {
|
enabled
|
||||||
delete checked[this.state.startIndex + i];
|
onOutsideRectEvent={this._handleHide}
|
||||||
} else {
|
>
|
||||||
checked[this.state.startIndex + i] = true;
|
<PopoverNavigation
|
||||||
}
|
style={{
|
||||||
this.setState({ checked });
|
top: "32px",
|
||||||
}}
|
right: "0px",
|
||||||
>
|
}}
|
||||||
<CheckBox
|
navigation={[
|
||||||
name={this.state.startIndex + i}
|
{
|
||||||
value={
|
text: "Copy CID",
|
||||||
!!this.state.checked[this.state.startIndex + i]
|
onClick: (e) => this._handleCopy(e, cid),
|
||||||
}
|
},
|
||||||
onChange={this._handleCheckBox}
|
{
|
||||||
boxStyle={{
|
text: "Copy link",
|
||||||
height: 24,
|
onClick: (e) =>
|
||||||
width: 24,
|
this._handleCopy(
|
||||||
backgroundColor: this.state.checked[
|
e,
|
||||||
this.state.startIndex + i
|
`${Constants.gateways.ipfs}/${cid}`
|
||||||
]
|
),
|
||||||
? Constants.system.brand
|
},
|
||||||
: "rgba(255, 255, 255, 0.75)",
|
{
|
||||||
|
text: "Delete",
|
||||||
|
onClick: (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.setState({ menu: null }, () =>
|
||||||
|
this._handleDelete(cid)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Boundary>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
let checked = this.state.checked;
|
||||||
|
if (checked[this.state.startIndex + i]) {
|
||||||
|
delete checked[this.state.startIndex + i];
|
||||||
|
} else {
|
||||||
|
checked[this.state.startIndex + i] = true;
|
||||||
|
}
|
||||||
|
this.setState({ checked });
|
||||||
}}
|
}}
|
||||||
style={{ position: "absolute", bottom: 8, left: 8 }}
|
>
|
||||||
/>
|
<CheckBox
|
||||||
</div>
|
name={this.state.startIndex + i}
|
||||||
</React.Fragment>
|
value={
|
||||||
) : null}
|
!!this.state.checked[this.state.startIndex + i]
|
||||||
|
}
|
||||||
|
onChange={this._handleCheckBox}
|
||||||
|
boxStyle={{
|
||||||
|
height: 24,
|
||||||
|
width: 24,
|
||||||
|
backgroundColor: this.state.checked[
|
||||||
|
this.state.startIndex + i
|
||||||
|
]
|
||||||
|
? Constants.system.brand
|
||||||
|
: "rgba(255, 255, 255, 0.75)",
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
bottom: 8,
|
||||||
|
left: 8,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
) : null}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -36,6 +36,10 @@ const STYLES_HEADER = css`
|
|||||||
max-width: 688px;
|
max-width: 688px;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
font-size: ${Constants.typescale.lvl3};
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_DESCRIPTION = css`
|
const STYLES_DESCRIPTION = css`
|
||||||
|
@ -8,7 +8,6 @@ import { LoaderSpinner } from "~/components/system/components/Loaders";
|
|||||||
const STYLES_DROPDOWN_CONTAINER = css`
|
const STYLES_DROPDOWN_CONTAINER = css`
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
z-index: ${Constants.zindex.modal};
|
z-index: ${Constants.zindex.modal};
|
||||||
height: 100%;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_DROPDOWN = css`
|
const STYLES_DROPDOWN = css`
|
||||||
@ -21,10 +20,16 @@ const STYLES_DROPDOWN = css`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
padding-bottom: 24px;
|
padding-bottom: 24px;
|
||||||
|
height: calc(100% - 16px);
|
||||||
|
overflow-y: scroll;
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
height: calc(100% - 36px);
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_DROPDOWN_ITEM = css`
|
const STYLES_DROPDOWN_ITEM = css`
|
||||||
|
@ -30,6 +30,11 @@ const STYLES_CONTAINER = css`
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background-color: ${Constants.system.white};
|
background-color: ${Constants.system.white};
|
||||||
box-shadow: 0 0 60px 8px rgba(0, 0, 0, 0.03);
|
box-shadow: 0 0 60px 8px rgba(0, 0, 0, 0.03);
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
max-width: 95vw;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_MODAL = css`
|
const STYLES_MODAL = css`
|
||||||
@ -42,8 +47,8 @@ const STYLES_MODAL = css`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_SEARCH_DROPDOWN = {
|
const STYLES_SEARCH_DROPDOWN = {
|
||||||
height: "calc(100% - 16px)",
|
// height: "calc(100% - 16px)",
|
||||||
overflowY: "scroll",
|
// overflowY: "scroll",
|
||||||
};
|
};
|
||||||
|
|
||||||
const STYLES_USER_ENTRY_CONTAINER = css`
|
const STYLES_USER_ENTRY_CONTAINER = css`
|
||||||
|
@ -2,6 +2,7 @@ import * as React from "react";
|
|||||||
import * as Constants from "~/common/constants";
|
import * as Constants from "~/common/constants";
|
||||||
import * as SVG from "~/common/svg";
|
import * as SVG from "~/common/svg";
|
||||||
import * as Strings from "~/common/strings";
|
import * as Strings from "~/common/strings";
|
||||||
|
import * as Validations from "~/common/validations";
|
||||||
import * as Actions from "~/common/actions";
|
import * as Actions from "~/common/actions";
|
||||||
|
|
||||||
import { Responsive, WidthProvider } from "react-grid-layout";
|
import { Responsive, WidthProvider } from "react-grid-layout";
|
||||||
@ -88,6 +89,12 @@ const STYLES_ACTION_BUTTON = css`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const STYLES_MOBILE_HIDDEN = css`
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const ResponsiveReactGridLayout = WidthProvider(Responsive);
|
const ResponsiveReactGridLayout = WidthProvider(Responsive);
|
||||||
|
|
||||||
const COLUMN_MAP = { lg: 12, md: 8, sm: 6, xs: 4, xxs: 2 };
|
const COLUMN_MAP = { lg: 12, md: 8, sm: 6, xs: 4, xxs: 2 };
|
||||||
@ -178,32 +185,42 @@ export default class Slate extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={index} css={STYLES_ITEM}>
|
<div
|
||||||
|
key={index}
|
||||||
|
css={STYLES_ITEM}
|
||||||
|
onClick={
|
||||||
|
Validations.onMobile()
|
||||||
|
? (e) => this._handleSelect(e, index)
|
||||||
|
: () => {}
|
||||||
|
}
|
||||||
|
>
|
||||||
<SlateMediaObjectPreview
|
<SlateMediaObjectPreview
|
||||||
charCap={70}
|
charCap={70}
|
||||||
type={data.type}
|
type={data.type}
|
||||||
url={data.url}
|
url={data.url}
|
||||||
title={data.title || data.name}
|
title={data.title || data.name}
|
||||||
/>
|
/>
|
||||||
<figure css={STYLES_BUTTON}>
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
<CircleButtonGray
|
<figure css={STYLES_BUTTON}>
|
||||||
style={{ margin: 8 }}
|
|
||||||
onMouseUp={(e) => this._handleSelect(e, index)}
|
|
||||||
onTouchEnd={(e) => this._handleSelect(e, index)}
|
|
||||||
>
|
|
||||||
<SVG.Eye height="16px" />
|
|
||||||
</CircleButtonGray>
|
|
||||||
|
|
||||||
{data.deeplink ? (
|
|
||||||
<CircleButtonGray
|
<CircleButtonGray
|
||||||
style={{ margin: 8 }}
|
style={{ margin: 8, cursor: "pointer" }}
|
||||||
onMouseUp={(e) => this._handleDeepLink(e, data)}
|
onMouseUp={(e) => this._handleSelect(e, index)}
|
||||||
onTouchEnd={(e) => this._handleDeepLink(e, data)}
|
onTouchEnd={(e) => this._handleSelect(e, index)}
|
||||||
>
|
>
|
||||||
<SVG.DeepLink height="16px" />
|
<SVG.Eye height="16px" />
|
||||||
</CircleButtonGray>
|
</CircleButtonGray>
|
||||||
) : null}
|
|
||||||
</figure>
|
{data.deeplink ? (
|
||||||
|
<CircleButtonGray
|
||||||
|
style={{ margin: 8 }}
|
||||||
|
onMouseUp={(e) => this._handleDeepLink(e, data)}
|
||||||
|
onTouchEnd={(e) => this._handleDeepLink(e, data)}
|
||||||
|
>
|
||||||
|
<SVG.DeepLink height="16px" />
|
||||||
|
</CircleButtonGray>
|
||||||
|
) : null}
|
||||||
|
</figure>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -245,8 +262,7 @@ export default class Slate extends React.Component {
|
|||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
css={STYLES_ACTION_BUTTON}
|
css={STYLES_ACTION_BUTTON}
|
||||||
onMouseUp={this._handleSaveLayout}
|
onClick={this._handleSaveLayout}
|
||||||
onTouchEnd={this._handleSaveLayout}
|
|
||||||
style={{
|
style={{
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
this.props.saving === "IDLE" ? Constants.system.brand : null,
|
this.props.saving === "IDLE" ? Constants.system.brand : null,
|
||||||
|
@ -5,6 +5,14 @@ import * as SVG from "~/common/svg";
|
|||||||
import { css } from "@emotion/react";
|
import { css } from "@emotion/react";
|
||||||
import { FileTypeIcon } from "~/components/core/FileTypeIcon";
|
import { FileTypeIcon } from "~/components/core/FileTypeIcon";
|
||||||
|
|
||||||
|
const STYLES_IMAGE_CONTAINER = css`
|
||||||
|
background-color: ${Constants.system.foreground};
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: 50% 50%;
|
||||||
|
`;
|
||||||
|
|
||||||
const STYLES_IMAGE = css`
|
const STYLES_IMAGE = css`
|
||||||
background-color: ${Constants.system.foreground};
|
background-color: ${Constants.system.foreground};
|
||||||
display: block;
|
display: block;
|
||||||
@ -53,6 +61,14 @@ export default class SlateMediaObjectPreview extends React.Component {
|
|||||||
: this.props.title;
|
: this.props.title;
|
||||||
|
|
||||||
if (this.props.type && this.props.type.startsWith("image/")) {
|
if (this.props.type && this.props.type.startsWith("image/")) {
|
||||||
|
if (this.props.centeredImage) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
css={STYLES_IMAGE_CONTAINER}
|
||||||
|
style={{ backgroundImage: `url(${url})`, ...this.props.imageStyle }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
return <img css={STYLES_IMAGE} style={this.props.imageStyle} src={url} />;
|
return <img css={STYLES_IMAGE} style={this.props.imageStyle} src={url} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,8 +323,7 @@ export default class SlateMediaObjectSidebar extends React.Component {
|
|||||||
<span
|
<span
|
||||||
key="sidebar-media-object-delete"
|
key="sidebar-media-object-delete"
|
||||||
css={STYLES_BUTTON}
|
css={STYLES_BUTTON}
|
||||||
onMouseUp={() => this.props.onDelete(this.props.id)}
|
onClick={() => this.props.onDelete(this.props.id)}
|
||||||
onTouchEnd={() => this.props.onDelete(this.props.id)}
|
|
||||||
>
|
>
|
||||||
{this.props.loading ? (
|
{this.props.loading ? (
|
||||||
<LoaderSpinner style={{ height: 16, width: 16 }} />
|
<LoaderSpinner style={{ height: 16, width: 16 }} />
|
||||||
|
@ -11,6 +11,18 @@ import { dispatchCustomEvent } from "~/common/custom-events";
|
|||||||
|
|
||||||
import SlateMediaObjectPreview from "~/components/core/SlateMediaObjectPreview";
|
import SlateMediaObjectPreview from "~/components/core/SlateMediaObjectPreview";
|
||||||
|
|
||||||
|
const STYLES_MOBILE_HIDDEN = css`
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_MOBILE_ONLY = css`
|
||||||
|
@media (min-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const STYLES_CREATE_NEW = css`
|
const STYLES_CREATE_NEW = css`
|
||||||
color: ${Constants.system.darkGray};
|
color: ${Constants.system.darkGray};
|
||||||
box-shadow: 0px 0px 0px 1px rgba(229, 229, 229, 0.5) inset;
|
box-shadow: 0px 0px 0px 1px rgba(229, 229, 229, 0.5) inset;
|
||||||
@ -23,7 +35,10 @@ const STYLES_CREATE_NEW = css`
|
|||||||
margin: 0px 12px;
|
margin: 0px 12px;
|
||||||
|
|
||||||
@media (max-width: ${Constants.sizes.mobile}px) {
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
margin: 0 8px;
|
margin: 0;
|
||||||
|
border-radius: 8;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -161,6 +176,11 @@ const STYLES_BLOCK = css`
|
|||||||
margin: 24px auto 48px auto;
|
margin: 24px auto 48px auto;
|
||||||
max-width: ${Constants.sizes.desktop}px;
|
max-width: ${Constants.sizes.desktop}px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
padding: 16px;
|
||||||
|
margin: 24px auto;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_TITLE_LINE = css`
|
const STYLES_TITLE_LINE = css`
|
||||||
@ -170,6 +190,10 @@ const STYLES_TITLE_LINE = css`
|
|||||||
font-size: ${Constants.typescale.lvl1};
|
font-size: ${Constants.typescale.lvl1};
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_COPY_INPUT = css`
|
const STYLES_COPY_INPUT = css`
|
||||||
@ -195,6 +219,10 @@ const STYLES_BODY = css`
|
|||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_ICON_BOX = css`
|
const STYLES_ICON_BOX = css`
|
||||||
@ -227,6 +255,20 @@ export default class SlatePreviewBlock extends React.Component {
|
|||||||
state = {
|
state = {
|
||||||
showMenu: false,
|
showMenu: false,
|
||||||
copyValue: "",
|
copyValue: "",
|
||||||
|
windowWidth: 360,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount = () => {
|
||||||
|
this.calculateWidth();
|
||||||
|
window.addEventListener("resize", this.calculateWidth);
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillUnmount = () => {
|
||||||
|
window.removeEventListener("resize", this.calculateWidth);
|
||||||
|
};
|
||||||
|
|
||||||
|
calculateWidth = () => {
|
||||||
|
this.setState({ windowWidth: window.innerWidth });
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleCopy = (e, value) => {
|
_handleCopy = (e, value) => {
|
||||||
@ -267,6 +309,9 @@ export default class SlatePreviewBlock extends React.Component {
|
|||||||
if (!this.props.editing && !this.props.slate.data.objects.length) {
|
if (!this.props.editing && !this.props.slate.data.objects.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
let first = this.props.slate.data.objects
|
||||||
|
? this.props.slate.data.objects[0]
|
||||||
|
: null;
|
||||||
let contextMenu = (
|
let contextMenu = (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Boundary
|
<Boundary
|
||||||
@ -387,10 +432,47 @@ export default class SlatePreviewBlock extends React.Component {
|
|||||||
) : (
|
) : (
|
||||||
<div style={{ height: "8px" }} />
|
<div style={{ height: "8px" }} />
|
||||||
)}
|
)}
|
||||||
<SlatePreviewRow
|
<span css={STYLES_MOBILE_ONLY}>
|
||||||
{...this.props}
|
<div
|
||||||
previewStyle={this.props.previewStyle}
|
css={STYLES_TITLE}
|
||||||
/>
|
style={{ marginBottom: 8, fontSize: Constants.typescale.lvl1 }}
|
||||||
|
>
|
||||||
|
{this.props.slate.data.name}
|
||||||
|
</div>
|
||||||
|
<div style={{ marginBottom: 16, fontSize: 12 }}>
|
||||||
|
{this.props.slate.data.objects.length} Object
|
||||||
|
{this.props.slate.data.objects.length === 1 ? "" : "s"}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: `${this.state.windowWidth - 80}px`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{first ? (
|
||||||
|
<SlateMediaObjectPreview
|
||||||
|
centeredImage
|
||||||
|
charCap={30}
|
||||||
|
type={first.type}
|
||||||
|
url={first.url}
|
||||||
|
style={{ borderRadius: 8 }}
|
||||||
|
imageStyle={{ borderRadius: 8 }}
|
||||||
|
title={first.title || first.name}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div css={STYLES_CREATE_NEW} key="add-files">
|
||||||
|
<SVG.Plus height="24px" />
|
||||||
|
<div>Add Files</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
|
<SlatePreviewRow
|
||||||
|
{...this.props}
|
||||||
|
previewStyle={this.props.previewStyle}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,11 @@ const STYLES_TAB_GROUP = css`
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
margin: 24px 0px 24px 0px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_TAB = css`
|
const STYLES_TAB = css`
|
||||||
@ -23,6 +28,7 @@ const STYLES_TAB = css`
|
|||||||
|
|
||||||
@media (max-width: ${Constants.sizes.mobile}px) {
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
|
font-size: ${Constants.typescale.lvl1};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -87,6 +87,34 @@ const STYLES_EXPANDER = css`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const STYLES_DISMISS_BOX = css`
|
||||||
|
position: absolute;
|
||||||
|
top: 16px;
|
||||||
|
right: 16px;
|
||||||
|
color: ${Constants.system.darkGray};
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
:hover {
|
||||||
|
color: ${Constants.system.black};
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_MOBILE_HIDDEN = css`
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_MOBILE_ONLY = css`
|
||||||
|
@media (min-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export class GlobalViewerCID extends React.Component {
|
export class GlobalViewerCID extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
index: 0,
|
index: 0,
|
||||||
@ -156,8 +184,11 @@ export class GlobalViewerCID extends React.Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleClose = () =>
|
_handleClose = (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
this.setState({ visible: false, index: 0, loading: false, saving: false });
|
this.setState({ visible: false, index: 0, loading: false, saving: false });
|
||||||
|
};
|
||||||
|
|
||||||
_handleCreate = (e) => {
|
_handleCreate = (e) => {
|
||||||
const shouldPersist =
|
const shouldPersist =
|
||||||
@ -202,44 +233,49 @@ export class GlobalViewerCID extends React.Component {
|
|||||||
<div css={STYLES_ROOT_CONTENT} style={this.props.style}>
|
<div css={STYLES_ROOT_CONTENT} style={this.props.style}>
|
||||||
<span
|
<span
|
||||||
css={STYLES_BOX}
|
css={STYLES_BOX}
|
||||||
onMouseUp={this._handlePrevious}
|
onClick={this._handlePrevious}
|
||||||
onTouchEnd={this._handlePrevious}
|
|
||||||
style={{ top: 0, left: 16, bottom: 0 }}
|
style={{ top: 0, left: 16, bottom: 0 }}
|
||||||
>
|
>
|
||||||
<SVG.ChevronLeft height="20px" />
|
<SVG.ChevronLeft height="20px" />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
css={STYLES_BOX}
|
css={STYLES_BOX}
|
||||||
onMouseUp={this._handleNext}
|
onClick={this._handleNext}
|
||||||
onTouchEnd={this._handleNext}
|
|
||||||
style={{ top: 0, right: 16, bottom: 0 }}
|
style={{ top: 0, right: 16, bottom: 0 }}
|
||||||
>
|
>
|
||||||
<SVG.ChevronRight height="20px" />
|
<SVG.ChevronRight height="20px" />
|
||||||
</span>
|
</span>
|
||||||
{current.component}
|
{current.component}
|
||||||
<div
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
css={STYLES_EXPANDER}
|
<div
|
||||||
onClick={() =>
|
css={STYLES_EXPANDER}
|
||||||
this.setState({ showSidebar: !this.state.showSidebar })
|
onClick={() =>
|
||||||
}
|
this.setState({ showSidebar: !this.state.showSidebar })
|
||||||
>
|
}
|
||||||
{this.state.showSidebar ? (
|
>
|
||||||
<SVG.Maximize height="24px" />
|
{this.state.showSidebar ? (
|
||||||
) : (
|
<SVG.Maximize height="24px" />
|
||||||
<SVG.Minimize height="24px" />
|
) : (
|
||||||
)}
|
<SVG.Minimize height="24px" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<div css={STYLES_DISMISS_BOX} onClick={this._handleClose}>
|
||||||
|
<SVG.Dismiss height="24px" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<GlobalViewerCIDSidebar
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
display={this.state.showSidebar ? "block" : "none"}
|
<GlobalViewerCIDSidebar
|
||||||
onClose={this._handleClose}
|
display={this.state.showSidebar ? "block" : "none"}
|
||||||
key={current.id}
|
onClose={this._handleClose}
|
||||||
saving={this.state.saving}
|
key={current.id}
|
||||||
loading={this.state.loading}
|
saving={this.state.saving}
|
||||||
onRehydrate={this.props.onRehydrate}
|
loading={this.state.loading}
|
||||||
onAction={this.props.onAction}
|
onRehydrate={this.props.onRehydrate}
|
||||||
{...current}
|
onAction={this.props.onAction}
|
||||||
/>
|
{...current}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -116,12 +116,7 @@ export default class GlobalViewerCIDSidebar extends React.Component {
|
|||||||
|
|
||||||
if (this.props.onClose) {
|
if (this.props.onClose) {
|
||||||
elements.push(
|
elements.push(
|
||||||
<div
|
<div key="s-1" css={STYLES_DISMISS_BOX} onClick={this.props.onClose}>
|
||||||
key="s-1"
|
|
||||||
css={STYLES_DISMISS_BOX}
|
|
||||||
onMouseUp={this.props.onClose}
|
|
||||||
onTouchEnd={this.props.onClose}
|
|
||||||
>
|
|
||||||
<SVG.Dismiss height="24px" />
|
<SVG.Dismiss height="24px" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -78,8 +78,7 @@ export const ButtonPrimary = (props) => {
|
|||||||
children={props.children}
|
children={props.children}
|
||||||
type={props.label}
|
type={props.label}
|
||||||
htmlFor={props.htmlFor}
|
htmlFor={props.htmlFor}
|
||||||
onMouseUp={props.onClick}
|
onClick={props.onClick}
|
||||||
onTouchEnd={props.onClick}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -92,8 +91,7 @@ export const ButtonPrimary = (props) => {
|
|||||||
: STYLES_BUTTON_PRIMARY
|
: STYLES_BUTTON_PRIMARY
|
||||||
}
|
}
|
||||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
onMouseUp={props.onClick}
|
onClick={props.onClick}
|
||||||
onTouchEnd={props.onClick}
|
|
||||||
children={props.children}
|
children={props.children}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -153,8 +151,7 @@ export const ButtonSecondary = (props) => {
|
|||||||
: STYLES_BUTTON_SECONDARY
|
: STYLES_BUTTON_SECONDARY
|
||||||
}
|
}
|
||||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
onMouseUp={props.onClick}
|
onClick={props.onClick}
|
||||||
onTouchEnd={props.onClick}
|
|
||||||
children={props.children}
|
children={props.children}
|
||||||
type={props.label}
|
type={props.label}
|
||||||
htmlFor={props.htmlFor}
|
htmlFor={props.htmlFor}
|
||||||
@ -169,8 +166,7 @@ export const ButtonSecondary = (props) => {
|
|||||||
? STYLES_BUTTON_SECONDARY_TRANSPARENT
|
? STYLES_BUTTON_SECONDARY_TRANSPARENT
|
||||||
: STYLES_BUTTON_SECONDARY
|
: STYLES_BUTTON_SECONDARY
|
||||||
}
|
}
|
||||||
onMouseUp={props.onClick}
|
onClick={props.onClick}
|
||||||
onTouchEnd={props.onClick}
|
|
||||||
children={props.children}
|
children={props.children}
|
||||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
/>
|
/>
|
||||||
@ -208,8 +204,7 @@ export const ButtonDisabled = (props) => {
|
|||||||
? STYLES_BUTTON_DISABLED_TRANSPARENT
|
? STYLES_BUTTON_DISABLED_TRANSPARENT
|
||||||
: STYLES_BUTTON_DISABLED
|
: STYLES_BUTTON_DISABLED
|
||||||
}
|
}
|
||||||
onMouseUp={props.onClick}
|
onClick={props.onClick}
|
||||||
onTouchEnd={props.onClick}
|
|
||||||
children={props.children}
|
children={props.children}
|
||||||
type={props.label}
|
type={props.label}
|
||||||
htmlFor={props.htmlFor}
|
htmlFor={props.htmlFor}
|
||||||
@ -275,8 +270,7 @@ export const ButtonWarning = (props) => {
|
|||||||
children={props.children}
|
children={props.children}
|
||||||
type={props.label}
|
type={props.label}
|
||||||
htmlFor={props.htmlFor}
|
htmlFor={props.htmlFor}
|
||||||
onMouseUp={props.onClick}
|
onClick={props.onClick}
|
||||||
onTouchEnd={props.onClick}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -289,8 +283,7 @@ export const ButtonWarning = (props) => {
|
|||||||
: STYLES_BUTTON_WARNING
|
: STYLES_BUTTON_WARNING
|
||||||
}
|
}
|
||||||
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
style={{ ...props.style, width: props.full ? "100%" : "auto" }}
|
||||||
onMouseUp={props.onClick}
|
onClick={props.onClick}
|
||||||
onTouchEnd={props.onClick}
|
|
||||||
children={props.children}
|
children={props.children}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -36,6 +36,10 @@ const STYLES_USER = css`
|
|||||||
color: ${Constants.system.brand};
|
color: ${Constants.system.brand};
|
||||||
font-family: ${Constants.font.medium};
|
font-family: ${Constants.font.medium};
|
||||||
font-size: ${Constants.typescale.lvl1};
|
font-size: ${Constants.typescale.lvl1};
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
margin: 12px 16px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_BUTTONS = css`
|
const STYLES_BUTTONS = css`
|
||||||
@ -43,6 +47,11 @@ const STYLES_BUTTONS = css`
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
margin-right: 48px;
|
margin-right: 48px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_ITEM_BOX = css`
|
const STYLES_ITEM_BOX = css`
|
||||||
@ -54,6 +63,10 @@ const STYLES_ITEM_BOX = css`
|
|||||||
padding: 8px;
|
padding: 8px;
|
||||||
margin-right: 48px;
|
margin-right: 48px;
|
||||||
color: ${Constants.system.darkGray};
|
color: ${Constants.system.darkGray};
|
||||||
|
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_ACTION_BUTTON = css`
|
const STYLES_ACTION_BUTTON = css`
|
||||||
@ -114,6 +127,18 @@ const STYLES_COPY_INPUT = css`
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const STYLES_MOBILE_HIDDEN = css`
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_MOBILE_ONLY = css`
|
||||||
|
@media (min-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export default class SceneDirectory extends React.Component {
|
export default class SceneDirectory extends React.Component {
|
||||||
_ref;
|
_ref;
|
||||||
|
|
||||||
@ -180,24 +205,53 @@ export default class SceneDirectory extends React.Component {
|
|||||||
})
|
})
|
||||||
.map((relation) => {
|
.map((relation) => {
|
||||||
let button = (
|
let button = (
|
||||||
<div css={STYLES_BUTTONS}>
|
<React.Fragment>
|
||||||
<ButtonPrimary
|
<span css={STYLES_MOBILE_ONLY}>
|
||||||
transparent
|
<div css={STYLES_BUTTONS}>
|
||||||
style={{ fontSize: 16 }}
|
<div
|
||||||
onClick={(e) => this._handleAccept(e, relation.owner.id)}
|
css={STYLES_ITEM_BOX}
|
||||||
>
|
onClick={(e) => this._handleAccept(e, relation.owner.id)}
|
||||||
Accept
|
>
|
||||||
</ButtonPrimary>
|
<SVG.CheckBox
|
||||||
<ButtonSecondary
|
height="24px"
|
||||||
transparent
|
style={{ color: Constants.system.brand }}
|
||||||
style={{ fontSize: 16 }}
|
/>
|
||||||
onClick={(e) => {
|
</div>
|
||||||
this._handleDelete(e, relation.id);
|
<div
|
||||||
}}
|
css={STYLES_ITEM_BOX}
|
||||||
>
|
style={{ marginRight: 0 }}
|
||||||
Decline
|
onClick={(e) => {
|
||||||
</ButtonSecondary>
|
this._handleDelete(e, relation.id);
|
||||||
</div>
|
}}
|
||||||
|
>
|
||||||
|
<SVG.Dismiss
|
||||||
|
height="24px"
|
||||||
|
style={{ color: Constants.system.gray }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<span css={STYLES_MOBILE_HIDDEN}>
|
||||||
|
<div css={STYLES_BUTTONS}>
|
||||||
|
<ButtonPrimary
|
||||||
|
transparent
|
||||||
|
style={{ fontSize: 16 }}
|
||||||
|
onClick={(e) => this._handleAccept(e, relation.owner.id)}
|
||||||
|
>
|
||||||
|
Accept
|
||||||
|
</ButtonPrimary>
|
||||||
|
<ButtonSecondary
|
||||||
|
transparent
|
||||||
|
style={{ fontSize: 16 }}
|
||||||
|
onClick={(e) => {
|
||||||
|
this._handleDelete(e, relation.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Decline
|
||||||
|
</ButtonSecondary>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<UserEntry
|
<UserEntry
|
||||||
|
@ -45,10 +45,7 @@ export default class SceneFilesFolder extends React.Component {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<TabGroup disabled tabs={["Usage"]} />
|
<TabGroup disabled tabs={["Usage"]} />
|
||||||
<DataMeter
|
<DataMeter stats={this.props.viewer.stats} />
|
||||||
stats={this.props.viewer.stats}
|
|
||||||
style={{ margin: "48px 0 48px 0" }}
|
|
||||||
/>
|
|
||||||
{this.props.viewer.library[0].children &&
|
{this.props.viewer.library[0].children &&
|
||||||
this.props.viewer.library[0].children.length ? (
|
this.props.viewer.library[0].children.length ? (
|
||||||
<DataView
|
<DataView
|
||||||
|
@ -2,6 +2,7 @@ import * as React from "react";
|
|||||||
import * as System from "~/components/system";
|
import * as System from "~/components/system";
|
||||||
import * as Actions from "~/common/actions";
|
import * as Actions from "~/common/actions";
|
||||||
import * as Constants from "~/common/constants";
|
import * as Constants from "~/common/constants";
|
||||||
|
import * as Validations from "~/common/validations";
|
||||||
import * as SVG from "~/common/svg";
|
import * as SVG from "~/common/svg";
|
||||||
import * as Strings from "~/common/strings";
|
import * as Strings from "~/common/strings";
|
||||||
import * as Window from "~/common/window";
|
import * as Window from "~/common/window";
|
||||||
@ -27,6 +28,12 @@ const STYLES_ICONS = css`
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const STYLES_ACTIONS = css`
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
padding-left: 24px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const STYLES_USERNAME = css`
|
const STYLES_USERNAME = css`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
@ -35,6 +42,18 @@ const STYLES_USERNAME = css`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const STYLES_MOBILE_HIDDEN = css`
|
||||||
|
@media (max-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const STYLES_MOBILE_ONLY = css`
|
||||||
|
@media (min-width: ${Constants.sizes.mobile}px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const moveIndex = (set, fromIndex, toIndex) => {
|
const moveIndex = (set, fromIndex, toIndex) => {
|
||||||
const element = set[fromIndex];
|
const element = set[fromIndex];
|
||||||
set.splice(fromIndex, 1);
|
set.splice(fromIndex, 1);
|
||||||
@ -416,6 +435,45 @@ export default class SceneSlate extends React.Component {
|
|||||||
return subscription.target_slate_id === this.props.current.id;
|
return subscription.target_slate_id === this.props.current.id;
|
||||||
}).length;
|
}).length;
|
||||||
|
|
||||||
|
let onMobile = Validations.onMobile();
|
||||||
|
let actions = this.state.editing ? (
|
||||||
|
<span css={STYLES_ACTIONS}>
|
||||||
|
<CircleButtonGray onClick={this._handleAdd} style={{ marginRight: 16 }}>
|
||||||
|
<SVG.Plus height="16px" />
|
||||||
|
</CircleButtonGray>
|
||||||
|
{isPublic ? (
|
||||||
|
<CircleButtonGray
|
||||||
|
onClick={() => this._handleSlateLink()}
|
||||||
|
style={{ marginRight: 16 }}
|
||||||
|
>
|
||||||
|
<SVG.DeepLink height="16px" />
|
||||||
|
</CircleButtonGray>
|
||||||
|
) : null}
|
||||||
|
<CircleButtonGray onClick={this._handleShowSettings}>
|
||||||
|
<SVG.Settings height="16px" />
|
||||||
|
</CircleButtonGray>
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<div onClick={this._handleFollow}>
|
||||||
|
{following ? (
|
||||||
|
<ButtonSecondary
|
||||||
|
transparent
|
||||||
|
style={{ minWidth: 120, paddingLeft: 0 }}
|
||||||
|
loading={this.state.followLoading}
|
||||||
|
>
|
||||||
|
Unfollow
|
||||||
|
</ButtonSecondary>
|
||||||
|
) : (
|
||||||
|
<ButtonPrimary
|
||||||
|
transparent
|
||||||
|
style={{ minWidth: 120, paddingLeft: 0 }}
|
||||||
|
loading={this.state.followLoading}
|
||||||
|
>
|
||||||
|
Follow
|
||||||
|
</ButtonPrimary>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<ScenePage
|
<ScenePage
|
||||||
style={{ paddingLeft: "24px", paddingRight: "24px" }}
|
style={{ paddingLeft: "24px", paddingRight: "24px" }}
|
||||||
@ -445,61 +503,15 @@ export default class SceneSlate extends React.Component {
|
|||||||
data.name
|
data.name
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
actions={
|
actions={<span css={STYLES_MOBILE_HIDDEN}>actions</span>}
|
||||||
this.state.editing ? (
|
|
||||||
<React.Fragment>
|
|
||||||
<CircleButtonGray
|
|
||||||
onMouseUp={this._handleAdd}
|
|
||||||
onTouchEnd={this._handleAdd}
|
|
||||||
style={{ marginRight: 16 }}
|
|
||||||
>
|
|
||||||
<SVG.Plus height="16px" />
|
|
||||||
</CircleButtonGray>
|
|
||||||
{isPublic ? (
|
|
||||||
<CircleButtonGray
|
|
||||||
onMouseUp={() => this._handleSlateLink()}
|
|
||||||
onTouchEnd={() => this._handleSlateLink()}
|
|
||||||
style={{ marginRight: 16 }}
|
|
||||||
>
|
|
||||||
<SVG.DeepLink height="16px" />
|
|
||||||
</CircleButtonGray>
|
|
||||||
) : null}
|
|
||||||
<CircleButtonGray
|
|
||||||
onMouseUp={this._handleShowSettings}
|
|
||||||
onTouchEnd={this._handleShowSettings}
|
|
||||||
>
|
|
||||||
<SVG.Settings height="16px" />
|
|
||||||
</CircleButtonGray>
|
|
||||||
</React.Fragment>
|
|
||||||
) : (
|
|
||||||
<div onClick={this._handleFollow}>
|
|
||||||
{following ? (
|
|
||||||
<ButtonSecondary
|
|
||||||
transparent
|
|
||||||
style={{ minWidth: 120 }}
|
|
||||||
loading={this.state.followLoading}
|
|
||||||
>
|
|
||||||
Unfollow
|
|
||||||
</ButtonSecondary>
|
|
||||||
) : (
|
|
||||||
<ButtonPrimary
|
|
||||||
transparent
|
|
||||||
style={{ minWidth: 120 }}
|
|
||||||
loading={this.state.followLoading}
|
|
||||||
>
|
|
||||||
Follow
|
|
||||||
</ButtonPrimary>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<ProcessedText text={body} />
|
<ProcessedText text={body} />
|
||||||
</ScenePageHeader>
|
</ScenePageHeader>
|
||||||
|
<span css={STYLES_MOBILE_ONLY}>{actions}</span>
|
||||||
{objects && objects.length ? (
|
{objects && objects.length ? (
|
||||||
layouts ? (
|
layouts ? (
|
||||||
<Slate
|
<Slate
|
||||||
editing={this.state.editing}
|
editing={onMobile ? false : this.state.editing}
|
||||||
saving={this.state.saving}
|
saving={this.state.saving}
|
||||||
items={objects}
|
items={objects}
|
||||||
layouts={layouts}
|
layouts={layouts}
|
||||||
|
@ -72,8 +72,7 @@ export default class SceneSlates extends React.Component {
|
|||||||
actions={
|
actions={
|
||||||
this.state.tab === 0 ? (
|
this.state.tab === 0 ? (
|
||||||
<CircleButtonGray
|
<CircleButtonGray
|
||||||
onMouseUp={this._handleAdd}
|
onClick={this._handleAdd}
|
||||||
onTouchEnd={this._handleAdd}
|
|
||||||
style={{ marginLeft: 12 }}
|
style={{ marginLeft: 12 }}
|
||||||
>
|
>
|
||||||
<SVG.Plus height="16px" />
|
<SVG.Plus height="16px" />
|
||||||
|
Loading…
Reference in New Issue
Block a user