chat: add expandable youtube embed messages

YouTube links now have a [embed] link that expands an inline embed of
the video. Embeds don't load until clicked, so don't fear the tracker.
This commit is contained in:
Anthony Arroyo 2019-12-06 16:35:03 -08:00 committed by Jared Tobin
parent 8f99735982
commit b96d6c5b5f
No known key found for this signature in database
GPG Key ID: 0E4647D58F8A69E4
4 changed files with 105 additions and 14 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;
}
/* 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 */
@media all and (max-width: 34.375em) {
@ -114,6 +129,9 @@ h2 {
.h-100-minus-96-s {
height: calc(100% - 96px);
}
.embed-container {
padding-bottom: 56.25%;
}
}
@media all and (min-width: 34.375em) and (max-width: 46.875em) {
@ -123,6 +141,9 @@ h2 {
.h-100-minus-48-m {
height: calc(100% - 48px);
}
.embed-container {
padding-bottom: 56.25%;
}
}
@media all and (min-width: 46.875em) and (max-width: 60em) {
@ -132,6 +153,9 @@ h2 {
.h-100-minus-48-l {
height: calc(100% - 48px);
}
.embed-container {
padding-bottom: 37.5%;
}
}
@media all and (min-width: 60em) {
@ -141,4 +165,7 @@ h2 {
.h-100-minus-48-xl {
height: calc(100% - 48px);
}
}
.embed-container {
padding-bottom: 28.125%;
}
}

View File

@ -8,14 +8,29 @@ import _ from 'lodash';
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() {
const { props } = this;
let letter = props.msg.letter;
if ('code' in letter) {
let outputElement =
(!!letter.code.output &&
let outputElement =
(!!letter.code.output &&
letter.code.output.length && letter.code.output.length > 0) ?
(
<pre className="clamp-attachment pa1 mt0 mb0">
@ -34,6 +49,15 @@ export class Message extends Component {
let imgMatch =
/(jpg|img|png|gif|tiff|jpeg|JPG|IMG|PNG|TIFF|GIF|webp|WEBP|webm|WEBM)$/
.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;
if (imgMatch) {
contents = (
@ -45,15 +69,55 @@ export class Message extends Component {
}}
></img>
);
}
return (
<a className="f7 lh-copy v-top bb b--black word-break-all"
return (
<a className="f7 lh-copy v-top bb 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}
target="_blank"
rel="noopener noreferrer">
{contents}
{letter.url}
</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) {
return (
<p className='f7 lh-copy v-top'>
@ -70,7 +134,7 @@ export class Message extends Component {
&& (chatroom[0] === letter.text))) { // entire message is room name?
return (
<Link
className="bb b--black f7 mono lh-copy v-top"
className="bb b--black f7 mono lh-copy v-top"
to={"/~chat/join/" + chatroom.input}>
{letter.text}
</Link>
@ -108,9 +172,9 @@ export class Message extends Component {
<Sigil
ship={props.msg.author}
size={24}
color={((props.msg.author === window.ship)
color={((props.msg.author === window.ship)
|| (props.msg.author.substr(1) === window.ship))
? "#4330FC"
? "#4330FC"
: "#000000"}
/>
</div>
@ -139,7 +203,7 @@ export class Message extends Component {
minHeight: "min-content"
}}>
<p className="child pt2 pl2 pr1 mono f9 gray dib">{timestamp}</p>
<div className="fr f7 clamp-message" style={{ flexGrow: 1 }}>
<div className="fr f7 clamp-message pr3" style={{ flexGrow: 1 }}>
{this.renderContent()}
</div>
</div>