mirror of
https://github.com/urbit/shrub.git
synced 2024-12-18 15:55:00 +03:00
link: front matter to preview component, imgs
This commit is contained in:
parent
deb3d26d3f
commit
112326a939
112
pkg/interface/link/src/js/components/lib/link-detail-preview.js
Normal file
112
pkg/interface/link/src/js/components/lib/link-detail-preview.js
Normal file
@ -0,0 +1,112 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Route, Link } from "react-router-dom";
|
||||
import moment from "moment";
|
||||
|
||||
export class LinkPreview extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
timeSinceLinkPost: this.getTimeSinceLinkPost(this.props.data)
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps !== this.props) {
|
||||
if (this.state.timeSinceLinkPost === "") {
|
||||
this.setState({
|
||||
timeSinceLinkPost: this.getTimeSinceLinkPost(this.props.data)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateTimeSinceNewestMessageInterval = setInterval(() => {
|
||||
this.setState({
|
||||
timeSinceLinkPost: this.getTimeSinceLinkPost(this.props.data)
|
||||
});
|
||||
}, 60000);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.updateTimeSinceNewestMessageInterval) {
|
||||
clearInterval(this.updateTimeSinceNewestMessageInterval);
|
||||
this.updateTimeSinceNewestMessageInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
getTimeSinceLinkPost(data) {
|
||||
return !!data.time
|
||||
? moment.unix(data.time / 1000).from(moment.utc())
|
||||
: "";
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
|
||||
let URLparser = new RegExp(
|
||||
/((?:([\w\d\.-]+)\:\/\/?){1}(?:(www)\.?){0,1}(((?:[\w\d-]+\.)*)([\w\d-]+\.[\w\d]+))){1}(?:\:(\d+)){0,1}((\/(?:(?:[^\/\s\?]+\/)*))(?:([^\?\/\s#]+?(?:.[^\?\s]+){0,1}){0,1}(?:\?([^\s#]+)){0,1})){0,1}(?:#([^#\s]+)){0,1}/
|
||||
);
|
||||
|
||||
let hostname = URLparser.exec(props.url);
|
||||
|
||||
if (hostname) {
|
||||
hostname = hostname[4];
|
||||
}
|
||||
|
||||
let imgMatch = /(jpg|img|png|gif|tiff|jpeg|JPG|IMG|PNG|TIFF|GIF|webp|WEBP|webm|WEBM)$/.exec(
|
||||
props.url
|
||||
);
|
||||
|
||||
let embed = "";
|
||||
|
||||
if (imgMatch) {
|
||||
embed = <img className="db w-50"
|
||||
src={props.url}
|
||||
style={{maxHeight: "100%", maxWidth: "500px", margin: "0 auto"}}/>
|
||||
}
|
||||
|
||||
let nameClass = props.nickname ? "inter" : "mono";
|
||||
|
||||
return (
|
||||
<div className="pb6 w-100">
|
||||
<div className="w-100"
|
||||
style={{maxHeight: "500px"}}>{embed}</div>
|
||||
<div className="flex flex-column ml2 pt6">
|
||||
<a href={props.url} className="w-100 flex" target="_blank">
|
||||
<p className="f8 truncate">
|
||||
{props.title}
|
||||
<span className="gray2 ml2 flex-shrink-0">
|
||||
{hostname} ↗
|
||||
</span>
|
||||
</p>
|
||||
</a>
|
||||
<div className="w-100 pt1">
|
||||
<span className={"f9 pr2 white-d v-mid " + nameClass}>
|
||||
{props.nickname ? props.nickname : "~" + props.ship}
|
||||
</span>
|
||||
<span className="f9 inter gray2 pr3 v-mid">
|
||||
{this.state.timeSinceLinkPost}
|
||||
</span>
|
||||
<Link
|
||||
to={
|
||||
"/~link" +
|
||||
props.path +
|
||||
"/" +
|
||||
props.page +
|
||||
"/" +
|
||||
props.linkIndex +
|
||||
"/" +
|
||||
window.btoa(props.url)
|
||||
}
|
||||
className="v-top">
|
||||
<span className="f9 inter gray2">{props.comments}</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default LinkPreview;
|
@ -3,17 +3,13 @@ import { LinksTabBar } from './lib/links-tabbar';
|
||||
import { SidebarSwitcher } from '/components/lib/icons/icon-sidebar-switch.js';
|
||||
import { api } from '../api';
|
||||
import { Route, Link } from 'react-router-dom';
|
||||
import { Sigil } from '/components/lib/icons/sigil';
|
||||
import { Comments } from './lib/comments';
|
||||
import { uxToHex } from '../lib/util';
|
||||
import moment from 'moment'
|
||||
import { base64urlEncode } from '../lib/util';
|
||||
|
||||
export class LinkDetail extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
timeSinceLinkPost: this.getTimeSinceLinkPost(props.data),
|
||||
comment: "",
|
||||
data: props.data
|
||||
};
|
||||
@ -23,8 +19,7 @@ export class LinkDetail extends Component {
|
||||
|
||||
updateData(submission) {
|
||||
this.setState({
|
||||
data: submission,
|
||||
timeSinceLinkPost: this.getTimeSinceLinkPost(submission)
|
||||
data: submission
|
||||
});
|
||||
}
|
||||
|
||||
@ -35,11 +30,6 @@ export class LinkDetail extends Component {
|
||||
this.props.groupPath, this.props.url, this.updateData.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
// start the time-since update timer
|
||||
this.updateTimeSinceNewestMessageInterval = setInterval( () => {
|
||||
this.setState({timeSinceLinkPost: this.getTimeSinceLinkPost(this.state.data)});
|
||||
}, 60000);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
@ -48,19 +38,6 @@ export class LinkDetail extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.updateTimeSinceNewestMessageInterval) {
|
||||
clearInterval(this.updateTimeSinceNewestMessageInterval);
|
||||
this.updateTimeSinceNewestMessageInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
getTimeSinceLinkPost(data) {
|
||||
return !!data.time ?
|
||||
moment.unix(data.time / 1000).from(moment.utc())
|
||||
: '';
|
||||
}
|
||||
|
||||
onClickPost() {
|
||||
let url = this.props.url || "";
|
||||
|
||||
@ -71,12 +48,12 @@ export class LinkDetail extends Component {
|
||||
);
|
||||
|
||||
if (request) {
|
||||
this.setState({comment: ""})
|
||||
this.setState({ comment: "" });
|
||||
}
|
||||
}
|
||||
|
||||
setComment(event) {
|
||||
this.setState({comment: event.target.value});
|
||||
this.setState({ comment: event.target.value });
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -88,124 +65,89 @@ export class LinkDetail extends Component {
|
||||
let title = data.title || "";
|
||||
let url = data.url || "";
|
||||
|
||||
let URLparser = new RegExp(/((?:([\w\d\.-]+)\:\/\/?){1}(?:(www)\.?){0,1}(((?:[\w\d-]+\.)*)([\w\d-]+\.[\w\d]+))){1}(?:\:(\d+)){0,1}((\/(?:(?:[^\/\s\?]+\/)*))(?:([^\?\/\s#]+?(?:.[^\?\s]+){0,1}){0,1}(?:\?([^\s#]+)){0,1})){0,1}(?:#([^#\s]+)){0,1}/);
|
||||
|
||||
let hostname = URLparser.exec(url);
|
||||
|
||||
if (hostname) {
|
||||
hostname = hostname[4];
|
||||
}
|
||||
|
||||
const commentCount = props.comments
|
||||
? props.comments.totalItems
|
||||
: data.commentCount || 0;
|
||||
|
||||
let comments = commentCount + " comment" + ((commentCount === 1) ? "" : "s");
|
||||
let comments = commentCount + " comment" + (commentCount === 1 ? "" : "s");
|
||||
|
||||
let nickname = !!props.members[ship]
|
||||
? props.members[ship].nickname
|
||||
: "";
|
||||
let nickname = !!props.members[ship] ? props.members[ship].nickname : "";
|
||||
|
||||
let nameClass = nickname ? "inter" : "mono";
|
||||
|
||||
let color = !!props.members[ship]
|
||||
? uxToHex(props.members[ship].color)
|
||||
: "000000";
|
||||
|
||||
let activeClasses = (this.state.comment)
|
||||
? "black b--black pointer"
|
||||
: "gray2 b--gray2";
|
||||
let activeClasses = this.state.comment
|
||||
? "black b--black pointer"
|
||||
: "gray2 b--gray2";
|
||||
|
||||
return (
|
||||
<div className="h-100 w-100 overflow-hidden flex flex-column">
|
||||
<div
|
||||
className={`pl3 pt2 flex relative overflow-x-scroll
|
||||
<div
|
||||
className={`pl3 pt2 flex relative overflow-x-scroll
|
||||
overflow-x-auto-l overflow-x-auto-xl flex-shrink-0
|
||||
bb bn-m bn-l bn-xl b--gray4`}
|
||||
style={{ height: 48 }}>
|
||||
<SidebarSwitcher
|
||||
sidebarShown={props.sidebarShown}
|
||||
popout={props.popout}/>
|
||||
<Link
|
||||
className="dib f8 fw4 v-top pt2 gray2"
|
||||
to={"/~link" + popout + props.groupPath + "/" + props.page}>
|
||||
{"<- Collection index"}
|
||||
</Link>
|
||||
<LinksTabBar
|
||||
{...props}
|
||||
popout={popout}
|
||||
groupPath={props.groupPath}/>
|
||||
</div>
|
||||
<div className="w-100 mt2 flex justify-center overflow-y-scroll ph4 pb4">
|
||||
<div className="w-100 mw7">
|
||||
<div className="pb6 flex">
|
||||
<Sigil
|
||||
ship={"~" + ship}
|
||||
size={36}
|
||||
color={"#" + color}
|
||||
style={{ height: 48 }}>
|
||||
<SidebarSwitcher
|
||||
sidebarShown={props.sidebarShown}
|
||||
popout={props.popout}
|
||||
/>
|
||||
<Link
|
||||
className="dib f8 fw4 v-top pt2 gray2"
|
||||
to={"/~link" + popout + props.groupPath + "/" + props.page}>
|
||||
{"<- Collection index"}
|
||||
</Link>
|
||||
<LinksTabBar {...props} popout={popout} groupPath={props.groupPath} />
|
||||
</div>
|
||||
<div className="w-100 mt2 flex justify-center overflow-y-scroll ph4 pb4">
|
||||
<div className="w-100 mw7">
|
||||
<LinkPreview
|
||||
title={title}
|
||||
url={url}
|
||||
comments={comments}
|
||||
nickname={nickname}
|
||||
ship={ship}
|
||||
path={props.groupPath}
|
||||
page={props.page}
|
||||
linkIndex={props.linkIndex}
|
||||
data={props.data}
|
||||
/>
|
||||
<div className="flex flex-column ml2">
|
||||
<a href={url}
|
||||
className="w-100 flex"
|
||||
target="_blank">
|
||||
<p className="f8 truncate">{title}
|
||||
<span className="gray2 ml2 flex-shrink-0">{hostname} ↗</span>
|
||||
</p>
|
||||
</a>
|
||||
<div className="w-100 pt1">
|
||||
<span className={"f9 pr2 white-d v-mid " + nameClass}>{(nickname)
|
||||
? nickname
|
||||
: "~" + ship}
|
||||
</span>
|
||||
<span className="f9 inter gray2 pr3 v-mid">
|
||||
{this.state.timeSinceLinkPost}
|
||||
</span>
|
||||
<Link to={"/~link" + props.path + "/" + props.page + "/" + props.linkIndex + "/" + base64urlEncode(props.url)} className="v-top">
|
||||
<span className="f9 inter gray2">
|
||||
{comments}
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative ba br1 b--gray4 b--gray2-d mt6 mb6">
|
||||
<textarea
|
||||
className="w-100 bg-gray0-d white-d f8 pa2 pr8"
|
||||
style={{
|
||||
resize: "none",
|
||||
height: 75
|
||||
}}
|
||||
placeholder="Leave a comment on this link"
|
||||
onChange={this.setComment}
|
||||
value={this.state.comment}
|
||||
className="w-100 bg-gray0-d white-d f8 pa2 pr8"
|
||||
style={{
|
||||
resize: "none",
|
||||
height: 75
|
||||
}}
|
||||
placeholder="Leave a comment on this link"
|
||||
onChange={this.setComment}
|
||||
value={this.state.comment}
|
||||
/>
|
||||
<button className={"f8 bg-gray0-d white-d ml2 absolute "
|
||||
+ activeClasses}
|
||||
disabled={!this.state.comment}
|
||||
onClick={this.onClickPost.bind(this)}
|
||||
style={{
|
||||
bottom: 12,
|
||||
right: 8
|
||||
}}>
|
||||
Post
|
||||
<button
|
||||
className={
|
||||
"f8 bg-gray0-d white-d ml2 absolute " + activeClasses
|
||||
}
|
||||
disabled={!this.state.comment}
|
||||
onClick={this.onClickPost.bind(this)}
|
||||
style={{
|
||||
bottom: 12,
|
||||
right: 8
|
||||
}}>
|
||||
Post
|
||||
</button>
|
||||
</div>
|
||||
<Comments
|
||||
groupPath={props.groupPath}
|
||||
key={props.groupPath + props.commentPage}
|
||||
comments={props.comments}
|
||||
commentPage={props.commentPage}
|
||||
members={props.members}
|
||||
popout={props.popout}
|
||||
url={props.url}
|
||||
linkPage={props.page}
|
||||
linkIndex={props.linkIndex}
|
||||
/>
|
||||
</div>
|
||||
<Comments
|
||||
groupPath={props.groupPath}
|
||||
key={props.groupPath + props.commentPage}
|
||||
comments={props.comments}
|
||||
commentPage={props.commentPage}
|
||||
members={props.members}
|
||||
popout={props.popout}
|
||||
url={props.url}
|
||||
linkPage={props.page}
|
||||
linkIndex={props.linkIndex}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default LinkDetail;
|
||||
export default LinkDetail;
|
||||
|
Loading…
Reference in New Issue
Block a user