import * as React from "react"; import * as Constants from "~/common/constants"; import * as System from "~/components/system"; import * as SVG from "~/common/svg"; import * as Strings from "~/common/strings"; import * as Actions from "~/common/actions"; import * as Validations from "~/common/validations"; import { css } from "@emotion/core"; import { ProcessedText } from "~/components/system/components/Typography"; import { Alert } from "~/components/core/Alert"; import { ViewAllButton } from "~/components/core/ViewAll"; import { SlateLayout } from "~/components/core/SlateLayout"; import { SlateLayoutMobile } from "~/components/core/SlateLayoutMobile"; import WebsitePrototypeWrapper from "~/components/core/WebsitePrototypeWrapper"; import WebsitePrototypeHeader from "~/components/core/WebsitePrototypeHeader"; import WebsitePrototypeFooter from "~/components/core/WebsitePrototypeFooter"; import SlateMediaObject from "~/components/core/SlateMediaObject"; import CTATransition from "~/components/core/CTATransition"; const SIZE_LIMIT = 1000000; //NOTE(martina): 1mb limit for twitter preview images const DEFAULT_IMAGE = "https://slate.textile.io/ipfs/bafkreiaow45dlq5xaydaeqocdxvffudibrzh2c6qandpqkb6t3ahbvh6re"; const DEFAULT_BOOK = "https://slate.textile.io/ipfs/bafkreibk32sw7arspy5kw3p5gkuidfcwjbwqyjdktd5wkqqxahvkm2qlyi"; const DEFAULT_DATA = "https://slate.textile.io/ipfs/bafkreid6bnjxz6fq2deuhehtxkcesjnjsa2itcdgyn754fddc7u72oks2m"; const DEFAULT_DOCUMENT = "https://slate.textile.io/ipfs/bafkreiecdiepww52i5q3luvp4ki2n34o6z3qkjmbk7pfhx4q654a4wxeam"; const DEFAULT_VIDEO = "https://slate.textile.io/ipfs/bafkreibesdtut4j5arclrxd2hmkfrv4js4cile7ajnndn3dcn5va6wzoaa"; const DEFAULT_AUDIO = "https://slate.textile.io/ipfs/bafkreig2hijckpamesp4nawrhd6vlfvrtzt7yau5wad4mzpm3kie5omv4e"; const STYLES_ROOT = css` display: block; min-height: 100vh; background-color: ${Constants.system.white}; `; const STYLES_SLATE_INTRO = css` display: flex; padding: 32px 64px; align-items: baseline; line-height: 1.3; word-wrap: break-word; @media (max-width: ${Constants.sizes.mobile}px) { padding: 32px 24px; display: block; font-size: 14px; } `; const STYLES_CREATOR = css` flex-shrink: 0; margin-right: 4px; text-decoration: none; color: ${Constants.system.black}; :hover { color: ${Constants.system.brand}; } :visited { color: ${Constants.system.black}; } `; const STYLES_DESCTIPTION = css` font-size: ${Constants.typescale.lvl1}; font-family: ${Constants.font.text}; width: 50%; word-wrap: break-word; @media (max-width: ${Constants.sizes.mobile}px) { width: 100%; margin-top: 4px; } `; const STYLES_TITLE = css` font-size: ${Constants.typescale.lvl3}; font-family: ${Constants.font.medium}; font-weight: 400; color: ${Constants.system.black}; width: auto; max-width: 100%; margin-right: 24px; word-wrap: break-word; @media (max-width: ${Constants.sizes.mobile}px) { font-size: ${Constants.typescale.lvl3}; } `; const STYLES_FLEX = css` display: flex; margin-bottom: 12px; @media (max-width: ${Constants.sizes.mobile}px) { display: block; } `; const STYLES_STATS = css` font-size: ${Constants.typescale.lvl0}; margin-top: 24px; display: flex; line-height: 1.5; `; const STYLES_STAT = css` margin-right: 48px; width: 88px; ${"" /* border-left: 1px solid ${Constants.system.darkGray}; padding-left: 12px; */}; `; const STYLES_BUTTONS = css` display: flex; width: 200px; height: 36px; border-radius: 4px; border: 1px solid ${Constants.system.gray}; flex-shrink: 0; @media (max-width: ${Constants.sizes.mobile}px) { margin: 12px 0; } `; const STYLES_BUTTON = css` border-right: 1px solid ${Constants.system.gray}; padding: 8px 4px; cursor: pointer; width: 50%; font-family: ${Constants.font.medium}; font-weight: 400; font-size: 14px; text-align: center; text-decoration: none; color: ${Constants.system.black}; :last-child { border-right: none; } :hover { background-color: ${Constants.system.gray}; transition: 200ms background-color linear; } :visited { color: ${Constants.system.black}; } `; const STYLES_SLATE = css` padding: 0 64px 0 64px; ${"" /* max-width: 1660px; */} display: block; width: 100%; margin: 48px auto 0 auto; min-height: 10%; height: 100%; @media (max-width: ${Constants.sizes.mobile}px) { padding: 0 24px 0 24px; } `; export const getServerSideProps = async (context) => { return { props: { ...context.query }, }; }; export const FileTypeDefaultPreview = () => { if (props.type && props.type.startsWith("video/")) { return DEFAULT_VIDEO; } if (props.type && props.type.startsWith("audio/")) { return DEFAULT_AUDIO; } if (props.type && props.type.startsWith("application/epub")) { return DEFAULT_BOOK; } if (props.type && props.type.startsWith("application/pdf")) { return DEFAULT_DOCUMENT; } return DEFAULT_DATA; }; export default class SlatePage extends React.Component { state = { visible: false, }; componentDidMount() { if (!this.props.slate) { return null; } let CIDMap = {}; System.dispatchCustomEvent({ name: "slate-global-create-carousel", detail: { carouselType: "slate", slides: this.props.slate.data.objects.map((each, index) => { // NOTE(jim): // This is a hack to catch this undefined case I don't want to track down yet. const url = each.url.replace("https://undefined", "https://"); const cid = Strings.getCIDFromIPFS(url); CIDMap[cid] = index; return { cid, id: each.id, data: each, isOwner: false, component: , }; }), }, }); if (!Strings.isEmpty(this.props.cid)) { const index = CIDMap[this.props.cid]; if (index || index === 0) { System.dispatchCustomEvent({ name: "slate-global-open-carousel", detail: { index, baseURL: `${this.props.creator.username}/${this.props.slate.slatename}`, }, }); } } } _handleSelect = (index) => System.dispatchCustomEvent({ name: "slate-global-open-carousel", detail: { index, baseURL: `${this.props.creator.username}/${this.props.slate.slatename}`, }, }); _handleSave = async (layouts) => { await Actions.updateSlate({ id: this.props.slate.id, layoutOnly: true, data: { layouts }, }); }; render() { let title = `${this.props.creator.username}/${this.props.slate.slatename}`; let url = `https://slate.host/${this.props.creator.username}/${this.props.slate.slatename}`; let headerURL = `https://slate.host/${this.props.creator.username}`; let { objects, layouts, body, preview } = this.props.slate.data; let image; if (Strings.isEmpty(this.props.cid)) { image = preview; if (Strings.isEmpty(image)) { for (let i = 0; i < objects.length; i++) { if ( objects[i].type && Validations.isPreviewableImage(objects[i].type) && objects[i].size && objects[i].size < SIZE_LIMIT ) { image = objects[i].url.replace("https://undefined", "https://"); break; } } } } else { let object = objects.find((each) => { const url = each.url.replace("https://undefined", "https://"); const cid = Strings.getCIDFromIPFS(url); return cid === this.props.cid; }); if (object) { title = !Strings.isEmpty(object.title) ? object.title : this.props.cid; body = !Strings.isEmpty(object.body) ? Strings.elide(object.body) : `An object on ${url}`; image = object.type.includes("image/") ? ( object.url ) : ( ); url = `${url}/cid:${this.props.cid}`; } } if (Strings.isEmpty(image)) { image = DEFAULT_IMAGE; } const slateCreator = `${this.props.creator.username} / `; const slateTitle = `${this.props.slate.slatename}`; const counts = objects.reduce((counts, { ownerId }) => { counts[ownerId] = (counts[ownerId] || 0) + 1; return counts; }, {}); const contributorsCount = Object.keys(counts).length; return (
{slateCreator}
{slateTitle}
this.setState({ visible: true })}> Follow
this.setState({ visible: true })}> Download
Data
{this.props.slate.data.objects.length}
Contributors
{contributorsCount}
{/*
Followers
0
*/}
{this.props.mobile ? ( ) : ( )}
{this.state.visible && (
this.setState({ visible: false })} viewer={this.props.viewer} open={this.state.visible} redirectURL={`/_?scene=V1_NAVIGATION_SLATE&user=${this.props.creator.username}&slate=${this.props.slate.slatename}`} />
)}
); } }