slate/scenes/SceneHome.js

305 lines
8.2 KiB
JavaScript
Raw Normal View History

2020-06-19 06:57:57 +03:00
import * as React from "react";
import * as Constants from "~/common/constants";
2020-12-04 02:34:19 +03:00
import * as Validations from "~/common/validations";
import * as Window from "~/common/window";
import * as SVG from "~/common/svg";
import * as Actions from "~/common/actions";
import * as Events from "~/common/custom-events";
2020-06-19 06:57:57 +03:00
import * as System from "~/components/system";
2020-11-30 08:24:22 +03:00
import { css } from "@emotion/react";
2020-06-19 06:57:57 +03:00
import ScenePage from "~/components/core/ScenePage";
2020-12-04 02:34:19 +03:00
import SlateMediaObjectPreview from "~/components/core/SlateMediaObjectPreview";
import DataView from "~/components/core/DataView";
2020-08-22 07:25:34 +03:00
import ScenePageHeader from "~/components/core/ScenePageHeader";
2020-09-08 07:04:24 +03:00
const STYLES_VIDEO_BIG = css`
display: block;
background-color: ${Constants.system.moonstone};
padding: 0;
outline: 0;
margin: 48px auto 88px auto;
border-radius: 4px;
width: 100%;
box-shadow: 0px 10px 50px 20px rgba(0, 0, 0, 0.1);
@media (max-width: ${Constants.sizes.tablet}px) {
margin: 32px auto 64px auto;
}
@media (max-width: ${Constants.sizes.mobile}px) {
margin: 24px auto 48px auto;
}
`;
2020-12-04 02:34:19 +03:00
const STYLES_IMAGE_BOX = css`
cursor: pointer;
position: relative;
box-shadow: ${Constants.shadow.light};
margin: 10px;
:hover {
box-shadow: ${Constants.shadow.medium};
}
`;
const STYLES_PROFILE_IMAGE_BOX = css`
background-size: cover;
background-position: 50% 50%;
position: relative;
border-radius: 4px;
position: absolute;
top: 16px;
left: 16px;
width: 24px;
height: 24px;
`;
2020-12-08 06:04:37 +03:00
const STYLES_TEXT_AREA = css`
2020-12-04 02:34:19 +03:00
position: absolute;
bottom: 16px;
left: 16px;
`;
const STYLES_TITLE = css`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: ${Constants.system.white};
2020-12-08 06:04:37 +03:00
font-family: ${Constants.font.medium};
margin-bottom: 4px;
`;
const STYLES_SECONDARY = css`
${STYLES_TITLE}
font-size: ${Constants.typescale.lvlN1};
margin-bottom: 0px;
2020-12-04 02:34:19 +03:00
`;
const STYLES_GRADIENT = css`
background: linear-gradient(
180deg,
rgba(0, 0, 0, 0) 0%,
rgba(0, 0, 0, 0.2) 26.56%,
rgba(0, 0, 0, 0.3) 100%
);
backdrop-filter: blur(2px);
width: 100%;
height: 72px;
position: absolute;
bottom: 0px;
left: 0px;
`;
2020-12-08 06:04:37 +03:00
const STYLES_ACTIVITY_GRID = css`
margin: -10px;
margin-top: 0px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
`;
2020-12-04 02:34:19 +03:00
const ActivitySquare = ({ item, size }) => {
2020-12-08 06:04:37 +03:00
let isImage = Validations.isPreviewableImage(item.file.type);
2020-12-04 02:34:19 +03:00
return (
<div css={STYLES_IMAGE_BOX} style={{ width: size, height: size }}>
<SlateMediaObjectPreview
centeredImage
iconOnly
blurhash={item.file.blurhash}
url={item.file.url}
title={item.file.title || item.file.name}
type={item.file.type}
style={{ border: "none" }}
imageStyle={{ border: "none" }}
/>
2020-12-08 06:04:37 +03:00
{isImage ? <div css={STYLES_GRADIENT} /> : null}
<div css={STYLES_TEXT_AREA}>
{isImage ? null : (
<div
css={STYLES_TITLE}
style={{
color: Constants.system.textGray,
width: size,
}}
>
{item.file.title || item.file.name}
</div>
)}
2020-12-04 02:34:19 +03:00
<div
2020-12-08 06:04:37 +03:00
css={STYLES_SECONDARY}
2020-12-04 02:34:19 +03:00
style={{
2020-12-08 06:04:37 +03:00
width: size,
color: isImage ? Constants.system.white : Constants.system.textGrayLight,
2020-12-04 02:34:19 +03:00
}}
>
2020-12-06 08:13:34 +03:00
{item.slate.data.name || item.slate.slatename}
2020-12-04 02:34:19 +03:00
</div>
</div>
</div>
);
};
const ActivityRectangle = ({ item, size }) => {
2020-12-06 08:13:34 +03:00
let file;
for (let obj of item.slate?.data?.objects || []) {
if (Validations.isPreviewableImage(obj.type) || obj.coverImage) {
file = obj;
}
}
let numObjects = item.slate?.data?.objects?.length || 0;
2020-12-04 02:34:19 +03:00
return (
2020-12-08 06:04:37 +03:00
<div css={STYLES_IMAGE_BOX} style={{ width: size * 2 + 20, height: size }}>
2020-12-06 08:13:34 +03:00
{file ? (
<SlateMediaObjectPreview
centeredImage
iconOnly
blurhash={file.blurhash}
url={file.url}
title={file.title || file.name}
type={file.type}
style={{ border: "none" }}
imageStyle={{ border: "none" }}
coverImage={file.coverImage}
/>
) : null}
2020-12-04 02:34:19 +03:00
<div css={STYLES_GRADIENT} />
2020-12-08 06:04:37 +03:00
<div css={STYLES_TEXT_AREA}>
2020-12-04 02:34:19 +03:00
<div
2020-12-08 06:04:37 +03:00
css={STYLES_TITLE}
2020-12-04 02:34:19 +03:00
style={{
fontFamily: Constants.font.semiBold,
2020-12-08 06:04:37 +03:00
width: size,
2020-12-04 02:34:19 +03:00
}}
>
2020-12-06 08:13:34 +03:00
{item.slate.data.name || item.slate.slatename}
2020-12-04 02:34:19 +03:00
</div>
<div
2020-12-08 06:04:37 +03:00
css={STYLES_SECONDARY}
2020-12-04 02:34:19 +03:00
style={{
color: Constants.system.textGrayLight,
2020-12-08 06:04:37 +03:00
width: size,
2020-12-04 02:34:19 +03:00
}}
>
{numObjects} File{numObjects == 1 ? "" : "s"}
</div>
</div>
</div>
);
};
export default class SceneHome extends React.Component {
2020-12-04 02:34:19 +03:00
state = {
imageSize: 200,
};
async componentDidMount() {
this.calculateWidth();
this.debounceInstance = Window.debounce(this.calculateWidth, 200);
window.addEventListener("resize", this.debounceInstance);
2020-12-08 06:04:37 +03:00
//slates with no previewable images in them?
2020-12-06 08:13:34 +03:00
//filter to remove ones you no longer follow
2020-12-04 02:34:19 +03:00
}
componentWillUnmount() {
window.removeEventListener("resize", this.debounceInstance);
}
_handleCreateSlate = () => {
this.props.onAction({
type: "NAVIGATE",
value: "V1_NAVIGATION_SLATES",
data: null,
});
};
2020-12-04 02:34:19 +03:00
calculateWidth = () => {
let windowWidth = window.innerWidth;
let imageSize;
if (windowWidth < Constants.sizes.mobile) {
imageSize = (windowWidth - 2 * 24 - 20) / 2;
} else {
2020-12-08 06:04:37 +03:00
imageSize = (windowWidth - 2 * 56 - 5 * 20) / 6;
}
2020-12-04 02:34:19 +03:00
this.setState({ imageSize });
};
2020-07-27 04:51:51 +03:00
2020-12-04 02:34:19 +03:00
render() {
2020-12-08 22:42:19 +03:00
let activity = this.props.viewer.activity;
return (
<ScenePage>
2020-12-08 22:42:19 +03:00
{activity.length ? (
2020-12-08 06:04:37 +03:00
<div css={STYLES_ACTIVITY_GRID}>
2020-12-08 22:42:19 +03:00
{activity.map((item) => {
2020-12-08 23:11:32 +03:00
if (item.data.type === "SUBSCRIBED_CREATE_SLATE") {
2020-12-06 08:13:34 +03:00
return (
<span
2020-12-08 06:04:37 +03:00
key={item.id}
2020-12-06 08:13:34 +03:00
onClick={() =>
this.props.onAction({
type: "NAVIGATE",
value: "V1_NAVIGATION_SLATE",
data: { decorator: "SLATE", ...item.data.context.slate },
})
}
>
2020-12-08 06:04:37 +03:00
<ActivityRectangle size={this.state.imageSize} item={item.data.context} />
2020-12-06 08:13:34 +03:00
</span>
);
2020-12-08 23:11:32 +03:00
} else if (item.data.type === "SUBSCRIBED_ADD_TO_SLATE") {
2020-12-06 08:13:34 +03:00
return (
2020-12-08 06:04:37 +03:00
<span
2020-12-06 08:13:34 +03:00
key={item.id}
2020-12-08 06:04:37 +03:00
onClick={() => {
this.props.onAction({
type: "NAVIGATE",
value: "V1_NAVIGATION_SLATE",
data: {
decorator: "SLATE",
...item.data.context.slate,
pageState: {
cid: item.data.context.file.cid,
},
},
});
}}
>
<ActivitySquare size={this.state.imageSize} item={item.data.context} />
</span>
2020-12-06 08:13:34 +03:00
);
} else {
2020-12-08 22:42:19 +03:00
return null;
2020-12-06 08:13:34 +03:00
}
})}
2020-09-08 01:16:02 +03:00
</div>
2020-09-08 07:04:24 +03:00
) : (
<React.Fragment>
2020-12-06 08:13:34 +03:00
<System.P>When you're ready, create a slate!</System.P>
<br />
<System.ButtonPrimary onClick={this._handleCreateSlate}>
Create a slate
</System.ButtonPrimary>
<video
css={STYLES_VIDEO_BIG}
autoPlay
loop
muted
src="https://slate.textile.io/ipfs/bafybeienjmql6lbtsaz3ycon3ttliohcl7qbquwvny43lhcodky54z65cy"
type="video/m4v"
playsInline
style={{
backgroundImage: `url('https://slate.textile.io/ipfs/bafybeienjmql6lbtsaz3ycon3ttliohcl7qbquwvny43lhcodky54z65cy')`,
borderRadius: `4px`,
width: `100%`,
boxShadow: `0px 10px 50px 20px rgba(0, 0, 0, 0.1)`,
backgroundSize: `cover`,
}}
/>
</React.Fragment>
2020-09-08 07:04:24 +03:00
)}
</ScenePage>
);
}
}