slates: you can link to slate objects directly now and copy and paste the URL bar to share with others

This commit is contained in:
@wwwjim 2020-09-13 19:58:33 -07:00
parent f6e9db5708
commit 6bb673d03f
5 changed files with 134 additions and 3 deletions

View File

@ -308,6 +308,19 @@ export default class SlateMediaObjectSidebar extends React.Component {
}
if (this.props.onDelete && this.props.editing) {
elements.push(
<a
key="sidebar-media-object-preview"
css={STYLES_BUTTON}
target="_blank"
href={`/${this.props.username}/${this.props.slatename}/cid:${
this.props.cid
}`}
>
View slate object public URL&nbsp;&nbsp;&nbsp;
</a>
);
elements.push(
<span
key="sidebar-media-object-delete"

View File

@ -131,12 +131,27 @@ export class GlobalCarousel extends React.Component {
index: e.detail.index || 0,
loading: false,
saving: false,
baseURL: e.detail.baseURL,
});
if (this.state.slides && e.detail.baseURL) {
const current = this.state.slides[e.detail.index];
window.history.replaceState(
{ index: e.detail.index },
"",
`/${e.detail.baseURL}/cid:${current.cid}`
);
}
};
_handleClose = () =>
_handleClose = () => {
this.setState({ visible: false, index: 0, loading: false, saving: false });
if (this.state.baseURL) {
window.history.replaceState({}, "", `/${this.state.baseURL}`);
}
};
_handleCreate = (e) => {
const shouldPersist =
this.state.visible && this.state.index < e.detail.slides.length;
@ -150,11 +165,24 @@ export class GlobalCarousel extends React.Component {
_handleDelete = (e) => {
this.setState({ slides: null, visible: false, index: 0 });
if (this.state.baseURL) {
window.history.replaceState({}, "", `/${this.state.baseURL}`);
}
};
_handleNext = () => {
const index = (this.state.index + 1) % this.state.slides.length;
this.setState({ index, loading: false, saving: false });
if (this.state.baseURL) {
const current = this.state.slides[index];
window.history.replaceState(
{ index },
"",
`/${this.state.baseURL}/cid:${current.cid}`
);
}
};
_handlePrevious = () => {
@ -162,6 +190,15 @@ export class GlobalCarousel extends React.Component {
(this.state.index + this.state.slides.length - 1) %
this.state.slides.length;
this.setState({ index, loading: false, saving: false });
if (this.state.baseURL) {
const current = this.state.slides[index];
window.history.replaceState(
{ index },
"",
`/${this.state.baseURL}/cid:${current.cid}`
);
}
};
render() {

View File

@ -2,6 +2,7 @@ import * as React from "react";
import * as Constants from "~/common/constants";
import * as System from "~/components/system";
import * as Strings from "~/common/strings";
import * as Window from "~/common/window";
import { css } from "@emotion/react";
import { ProcessedText } from "~/components/system/components/Typography";
@ -55,14 +56,16 @@ export default class SlatePage extends React.Component {
return null;
}
let CIDMap = {};
System.dispatchCustomEvent({
name: "slate-global-create-carousel",
detail: {
slides: this.props.slate.data.objects.map((each) => {
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,
@ -76,12 +79,31 @@ export default class SlatePage extends React.Component {
}),
},
});
if (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 },
detail: {
index,
baseURL: `${this.props.creator.username}/${this.props.slate.slatename}`,
},
});
render() {

View File

@ -289,6 +289,8 @@ export default class SceneSlate extends React.Component {
id: data.id,
cid,
data,
username: this.props.viewer.username,
slatename: this.props.current.slatename,
editing: this.state.editing,
component: <SlateMediaObject key={each.id} data={data} />,
};

View File

@ -136,6 +136,10 @@ app.prepare().then(async () => {
return res.redirect("/404");
}
if (slate.error) {
return res.redirect("/404");
}
if (!slate.data.public) {
return res.redirect("/403");
}
@ -170,6 +174,59 @@ app.prepare().then(async () => {
});
});
server.get("/:username/:slatename/cid::cid", async (req, res) => {
// TODO(jim): Temporary workaround
if (!Validations.userRoute(req.params.username)) {
return handler(req, res, req.url);
}
const slate = await Data.getSlateByName({
slatename: req.params.slatename,
});
if (!slate) {
return res.redirect("/404");
}
if (slate.error) {
return res.redirect("/404");
}
if (!slate.data.public) {
return res.redirect("/403");
}
const creator = await Data.getUserById({ id: slate.data.ownerId });
if (!creator) {
return res.redirect("/404");
}
if (creator.error) {
return res.redirect("/404");
}
if (req.params.username !== creator.username) {
return res.redirect("/403");
}
const id = Utilities.getIdFromCookie(req);
let viewer = null;
if (id) {
viewer = await ViewerManager.getById({
id,
});
}
return app.render(req, res, "/_/slate", {
viewer,
creator: Serializers.user(creator),
slate,
cid: req.params.cid,
});
});
server.all("*", async (r, s) => handler(r, s, r.url));
server.listen(Environment.PORT, async (e) => {