Merge branch 'yt-preview' (#2055)

* origin/yt-preview:
  chat: add expandable youtube embed messages

Signed-off-by: Jared Tobin <jared@tlon.io>
This commit is contained in:
Jared Tobin 2020-01-22 15:14:37 +04:00
commit 267081424b
No known key found for this signature in database
GPG Key ID: 0E4647D58F8A69E4
4 changed files with 101 additions and 10 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -99,6 +99,21 @@ h2 {
word-break: break-all; word-break: break-all;
} }
/* embeds */
.embed-container {
position: relative;
height: 0;
overflow: hidden;
}
.embed-container iframe, .embed-container object, .embed-container embed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* responsive */ /* responsive */
@media all and (max-width: 34.375em) { @media all and (max-width: 34.375em) {
@ -114,6 +129,9 @@ h2 {
.h-100-minus-96-s { .h-100-minus-96-s {
height: calc(100% - 96px); height: calc(100% - 96px);
} }
.embed-container {
padding-bottom: 56.25%;
}
} }
@media all and (min-width: 34.375em) and (max-width: 46.875em) { @media all and (min-width: 34.375em) and (max-width: 46.875em) {
@ -123,6 +141,9 @@ h2 {
.h-100-minus-48-m { .h-100-minus-48-m {
height: calc(100% - 48px); height: calc(100% - 48px);
} }
.embed-container {
padding-bottom: 56.25%;
}
} }
@media all and (min-width: 46.875em) and (max-width: 60em) { @media all and (min-width: 46.875em) and (max-width: 60em) {
@ -132,6 +153,9 @@ h2 {
.h-100-minus-48-l { .h-100-minus-48-l {
height: calc(100% - 48px); height: calc(100% - 48px);
} }
.embed-container {
padding-bottom: 37.5%;
}
} }
@media all and (min-width: 60em) { @media all and (min-width: 60em) {
@ -141,6 +165,9 @@ h2 {
.h-100-minus-48-xl { .h-100-minus-48-xl {
height: calc(100% - 48px); height: calc(100% - 48px);
} }
.embed-container {
padding-bottom: 28.125%;
}
} }
/* dark */ /* dark */
@ -186,4 +213,4 @@ h2 {
a { a {
color: #fff; color: #fff;
} }
} }

View File

@ -8,6 +8,21 @@ import _ from 'lodash';
export class Message extends Component { export class Message extends Component {
constructor() {
super();
this.state = {
unfold: false
};
this.unFoldEmbed = this.unFoldEmbed.bind(this);
}
unFoldEmbed(id) {
let unfoldState = this.state.unfold;
unfoldState = !unfoldState;
this.setState({unfold: unfoldState});
let iframe = this.refs.iframe;
iframe.setAttribute('src', iframe.getAttribute('data-src'));
}
renderContent() { renderContent() {
const { props } = this; const { props } = this;
@ -34,6 +49,15 @@ export class Message extends Component {
let imgMatch = let imgMatch =
/(jpg|img|png|gif|tiff|jpeg|JPG|IMG|PNG|TIFF|GIF|webp|WEBP|webm|WEBM)$/ /(jpg|img|png|gif|tiff|jpeg|JPG|IMG|PNG|TIFF|GIF|webp|WEBP|webm|WEBM)$/
.exec(letter.url); .exec(letter.url);
// this is jank
// TODO do we know ID lenght?
let youTubeRegex = new RegExp(''
+ /(?:https?:\/\/(?:[a-z]+.)?)/.source // protocol
+ /(?:youtu\.?be(?:\.com)?\/)(?:embed\/)?/.source // short and long-links
+ /(?:(?:(?:(?:watch\?)?(?:time_continue=(?:[0-9]+))?.+v=)?([a-zA-Z0-9_-]+))(?:\?t\=(?:[0-9a-zA-Z]+))?)/.source // id
)
let ytMatch =
youTubeRegex.exec(letter.url);
let contents = letter.url; let contents = letter.url;
if (imgMatch) { if (imgMatch) {
contents = ( contents = (
@ -46,15 +70,55 @@ export class Message extends Component {
}} }}
></img> ></img>
); );
} return (
return ( <a className="f7 lh-copy v-top bb word-break-all"
<a className="f7 lh-copy v-top bb b--black word-break-all" href={letter.url}
target="_blank"
rel="noopener noreferrer">
{contents}
</a>
);
} else if (ytMatch) {
contents = (
<div className={'embed-container mb2 w-100 w-75-l w-50-xl ' +
((this.state.unfold === true)
? "db"
: "dn")}>
<iframe
ref="iframe"
width="560"
height="315"
data-src={`https://www.youtube.com/embed/${ytMatch[1]}`}
frameBorder="0" allow="picture-in-picture, fullscreen">
</iframe>
</div>
)
return (
<div>
<a href={letter.url}
className="f7 lh-copy v-top bb word-break-all"
href={letter.url} href={letter.url}
target="_blank" target="_blank"
rel="noopener noreferrer"> rel="noopener noreferrer">
{contents} {letter.url}
</a> </a>
); <a className="f7 pointer pl2 lh-copy v-top word-break-all"
onClick={e => this.unFoldEmbed()}>
[embed]
</a>
{contents}
</div>
)
} else {
return (
<a className="f7 lh-copy v-top bb b--black word-break-all"
href={letter.url}
target="_blank"
rel="noopener noreferrer">
{contents}
</a>
);
}
} else if ('me' in letter) { } else if ('me' in letter) {
return ( return (
<p className='f7 i lh-copy v-top'> <p className='f7 i lh-copy v-top'>
@ -140,8 +204,8 @@ export class Message extends Component {
minHeight: "min-content" minHeight: "min-content"
}}> }}>
<p className="child pt2 pl2 pr1 mono f9 gray2 dib">{timestamp}</p> <p className="child pt2 pl2 pr1 mono f9 gray2 dib">{timestamp}</p>
<div className="fr f7 clamp-message white-d" style={{ flexGrow: 1 }}> <div className="fr f7 clamp-message white-d pr3" style={{ flexGrow: 1 }}>
{this.renderContent()} {this.renderContent()}
</div> </div>
</div> </div>
); );