Skip to content
Snippets Groups Projects
Commit 4b2274ee authored by Tim's avatar Tim
Browse files

initial video embed

parent e91c4f8e
No related branches found
No related tags found
No related merge requests found
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M19,19H5V5H19M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M10,8V16L15,12L10,8Z" /></svg>
\ No newline at end of file
......@@ -30,6 +30,7 @@ const icons = [
'reblog',
'photo',
'line',
'video',
];
const icons_map = {};
for (const i of icons) icons_map[i] = require(`app/assets/icons/${i}.svg`);
......
......@@ -367,6 +367,7 @@ console.log(JSON.stringify(Raw.serialize(state, {terse: false}), null, 2))
<Portal isOpened onOpen={this.onSidebarOpen}>
<div className="SlateEditor__sidebar">
{this.renderAddBlockButton({type: 'image', label: <Icon name="photo" />, handler: this.onClickInsertImage})}
{this.renderAddBlockButton({type: 'video', label: <Icon name="video" />, handler: this.onClickInsertVideo})}
{this.renderAddBlockButton({type: 'hrule', label: <Icon name="line" />, handler: this.onClickInsertHr})}
</div>
</Portal>
......@@ -383,8 +384,22 @@ console.log(JSON.stringify(Raw.serialize(state, {terse: false}), null, 2))
state = state
.transform()
.insertInline({type: 'image', isVoid: true, data: {src}})
.insertBlock({type: 'paragraph', isVoid: false, nodes: [Slate.Text.create()]})
//.insertBlock({type: 'paragraph', isVoid: false, nodes: [Slate.Text.create()]})
.focus()
.collapseToEndOfNextBlock()
.apply()
this.setState({ state })
}
onClickInsertVideo = (e, type) => {
e.preventDefault()
let { state } = this.state
state = state
.transform()
.insertBlock({type: 'embed', isVoid: true, data: {src: 'https://www.youtube.com/watch?v=7YOozVnEdFQ'}})
.insertBlock({type: 'paragraph', isVoid: false})
.apply()
this.setState({ state })
......
......@@ -4,6 +4,7 @@
position: relative;
img {border: 1px dotted #00f}
}
div.active,
img.active {box-shadow: 0 0 2px 1px #48C;}
hr.active {box-shadow: 0 0 2px 1px #48C;}
......
import React from 'react'
import linksRe from 'app/utils/Links'
export default class Iframe extends React.Component {
normalizeEmbedUrl = (url) => {
// Detect youtube URLs
const match = url.match(linksRe.youTubeId)
if(match && match.length >= 2) {
return 'https://www.youtube.com/embed/' + match[1]
}
console.log("unable to auto-detect embed url", url)
return null
}
onChange = (e) => {
const { node, state, editor } = this.props
const value = e.target.value
const src = this.normalizeEmbedUrl(value) || value
const next = editor
.getState()
.transform()
.setNodeByKey(node.key, {data: {src}})
.apply()
editor.onChange(next)
}
onClick = (e) => {
// stop propagation so that the void node itself isn't focused, since that would unfocus the input.
e.stopPropagation()
}
render = () => {
const { node, state, attributes } = this.props
const isFocused = state.selection.hasEdgeIn(node)
const className = isFocused ? 'active' : null
const style = {background: 'black', color: 'white'}
return (
<div {...attributes} className={className} style={style}>
{this.renderFrame()}
Embed URL: {this.renderInput()}
</div>
)
}
renderFrame = () => {
let src = this.props.node.data.get('src')
src = this.normalizeEmbedUrl(src) || src
const aspectStyle = {
position: 'relative',
paddingBottom: '56.2%',
height: '0'
}
const lockStyle = {
position: 'absolute',
top: '0px',
left: '0px',
width: '100%',
height: '100%',
background: 'rgba(0,0,0,0.1)'
}
const style = {
position: 'absolute',
top: '0px',
left: '0px',
width: '100%',
height: '100%'
}
return (
<div style={aspectStyle}>
<iframe
type="text/html"
width="640"
height="360"
src={src}
frameBorder="0"
style={style}>
</iframe>
<div style={lockStyle}></div>
</div>
)
}
renderInput = () => {
const src = this.props.node.data.get('src')
return (
<input
value={src}
onChange={this.onChange}
onClick={this.onClick}
style={{ marginTop: '5px', background: 'black' }}
size="70"
/>
)
}
}
import React from 'react'
import Link from 'app/utils/SlateEditor/Link'
import Image from 'app/utils/SlateEditor/Image'
import Iframe from 'app/utils/SlateEditor/Iframe'
import HRule from 'app/utils/SlateEditor/HRule'
......@@ -211,6 +212,7 @@ export const schema = {
'hr': HRule,
'image': Image,
'link': Link,
'embed': Iframe,
},
marks: {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment