Fixed youtube link rendering
This commit is contained in:
parent
9c4e660b16
commit
3d2d44d193
2 changed files with 78 additions and 51 deletions
|
@ -7,6 +7,7 @@ import * as React from "react";
|
||||||
import ReactRenderer from "vendor/xbbcode/renderer/react";
|
import ReactRenderer from "vendor/xbbcode/renderer/react";
|
||||||
import {rendererReact, rendererText, BBCodeHandlerContext} from "tc-shared/text/bbcode/renderer";
|
import {rendererReact, rendererText, BBCodeHandlerContext} from "tc-shared/text/bbcode/renderer";
|
||||||
import {ClientTag} from "tc-shared/ui/tree/EntryTags";
|
import {ClientTag} from "tc-shared/ui/tree/EntryTags";
|
||||||
|
import {isYoutubeLink, YoutubeRenderer} from "tc-shared/text/bbcode/youtube";
|
||||||
|
|
||||||
function spawnUrlContextMenu(pageX: number, pageY: number, target: string) {
|
function spawnUrlContextMenu(pageX: number, pageY: number, target: string) {
|
||||||
contextmenu.spawn_context_menu(pageX, pageY, {
|
contextmenu.spawn_context_menu(pageX, pageY, {
|
||||||
|
@ -74,7 +75,7 @@ loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
const body = (
|
||||||
<a key={"er-" + ++reactId} className={"xbbcode xbbcode-tag-url"} href={target} target={"_blank"} onContextMenu={event => {
|
<a key={"er-" + ++reactId} className={"xbbcode xbbcode-tag-url"} href={target} target={"_blank"} onContextMenu={event => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
spawnUrlContextMenu(event.pageX, event.pageY, target);
|
spawnUrlContextMenu(event.pageX, event.pageY, target);
|
||||||
|
@ -82,6 +83,14 @@ loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
{renderer.renderContent(element)}
|
{renderer.renderContent(element)}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if(isYoutubeLink(target)) {
|
||||||
|
return (
|
||||||
|
<YoutubeRenderer url={target}>{body}</YoutubeRenderer>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
</BBCodeHandlerContext.Consumer>
|
</BBCodeHandlerContext.Consumer>
|
||||||
);
|
);
|
||||||
|
|
|
@ -14,63 +14,81 @@ import {server_connections} from "tc-shared/ConnectionManager";
|
||||||
const playIcon = require("./yt-play-button.svg");
|
const playIcon = require("./yt-play-button.svg");
|
||||||
const cssStyle = require("./youtube.scss");
|
const cssStyle = require("./youtube.scss");
|
||||||
|
|
||||||
|
const patternYtVideoId = /^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\/))([^?&"'>]{10,11})$/;
|
||||||
|
let reactId = 0;
|
||||||
|
|
||||||
|
export const isYoutubeLink = (text: string) => {
|
||||||
|
const result = text.match(patternYtVideoId);
|
||||||
|
return !(!result || !result[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const YoutubeRenderer = (props: { children?: React.ReactElement | React.ReactElement[], url: string }) => {
|
||||||
|
const result = props.url.match(patternYtVideoId);
|
||||||
|
if(!result || !result[1]) {
|
||||||
|
if(props.children) {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={"fallback"}>
|
||||||
|
{props.children}
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return <BBCodeRenderer key={"cyt-" + ++reactId} settings={{ convertSingleUrls: false }} message={"[url]" + props.url + "[/url]"} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cssStyle.container}
|
||||||
|
onContextMenu={event => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
spawn_context_menu(event.pageX, event.pageY, {
|
||||||
|
callback: () => {
|
||||||
|
global_client_actions.fire("action_w2g", {
|
||||||
|
videoUrl: props.url,
|
||||||
|
handlerId: server_connections.active_connection().handlerId
|
||||||
|
});
|
||||||
|
},
|
||||||
|
name: tr("Watch video"),
|
||||||
|
type: contextmenu.MenuEntryType.ENTRY,
|
||||||
|
icon_class: ""
|
||||||
|
}, {
|
||||||
|
callback: () => {
|
||||||
|
const win = window.open(props.url, '_blank');
|
||||||
|
win.focus();
|
||||||
|
},
|
||||||
|
name: tr("Open video URL"),
|
||||||
|
type: contextmenu.MenuEntryType.ENTRY,
|
||||||
|
icon_class: "client-browse-addon-online"
|
||||||
|
}, contextmenu.Entry.HR(), {
|
||||||
|
callback: () => copy_to_clipboard(props.url),
|
||||||
|
name: tr("Copy video URL to clipboard"),
|
||||||
|
type: contextmenu.MenuEntryType.ENTRY,
|
||||||
|
icon_class: "client-copy"
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img draggable={false} src={"https://img.youtube.com/vi/" + result[1] + "/hqdefault.jpg"} alt={"Video thumbnail"} title={tra("Youtube video {}", result[1])} />
|
||||||
|
<button className={cssStyle.playButton} onClick={() => {
|
||||||
|
global_client_actions.fire("action_w2g", {
|
||||||
|
videoUrl: props.url,
|
||||||
|
handlerId: server_connections.active_connection().handlerId
|
||||||
|
});
|
||||||
|
}}>
|
||||||
|
<HTMLRenderer purify={false}>{playIcon}</HTMLRenderer>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
name: "XBBCode code tag init",
|
name: "XBBCode code tag init",
|
||||||
function: async () => {
|
function: async () => {
|
||||||
let reactId = 0;
|
|
||||||
|
|
||||||
const patternYtVideoId = /^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\/))([^?&"'>]{10,11})$/;
|
|
||||||
rendererReact.registerCustomRenderer(new class extends ElementRenderer<TagElement, React.ReactNode> {
|
rendererReact.registerCustomRenderer(new class extends ElementRenderer<TagElement, React.ReactNode> {
|
||||||
render(element: TagElement): React.ReactNode {
|
render(element: TagElement): React.ReactNode {
|
||||||
const text = rendererText.render(element);
|
const text = rendererText.render(element);
|
||||||
const result = text.match(patternYtVideoId);
|
return <YoutubeRenderer url={text} />;
|
||||||
if(!result || !result[1]) {
|
|
||||||
return <BBCodeRenderer key={"cyt-" + ++reactId} settings={{ convertSingleUrls: false }} message={"[url]" + text + "[/url]"} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={cssStyle.container}
|
|
||||||
onContextMenu={event => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
spawn_context_menu(event.pageX, event.pageY, {
|
|
||||||
callback: () => {
|
|
||||||
global_client_actions.fire("action_w2g", {
|
|
||||||
videoUrl: text,
|
|
||||||
handlerId: server_connections.active_connection().handlerId
|
|
||||||
});
|
|
||||||
},
|
|
||||||
name: tr("Watch video"),
|
|
||||||
type: contextmenu.MenuEntryType.ENTRY,
|
|
||||||
icon_class: ""
|
|
||||||
}, {
|
|
||||||
callback: () => {
|
|
||||||
const win = window.open(text, '_blank');
|
|
||||||
win.focus();
|
|
||||||
},
|
|
||||||
name: tr("Open video URL"),
|
|
||||||
type: contextmenu.MenuEntryType.ENTRY,
|
|
||||||
icon_class: "client-browse-addon-online"
|
|
||||||
}, contextmenu.Entry.HR(), {
|
|
||||||
callback: () => copy_to_clipboard(text),
|
|
||||||
name: tr("Copy video URL to clipboard"),
|
|
||||||
type: contextmenu.MenuEntryType.ENTRY,
|
|
||||||
icon_class: "client-copy"
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<img draggable={false} src={"https://img.youtube.com/vi/" + result[1] + "/hqdefault.jpg"} alt={"Video thumbnail"} title={tra("Youtube video {}", result[1])} />
|
|
||||||
<button className={cssStyle.playButton} onClick={() => {
|
|
||||||
global_client_actions.fire("action_w2g", {
|
|
||||||
videoUrl: text,
|
|
||||||
handlerId: server_connections.active_connection().handlerId
|
|
||||||
});
|
|
||||||
}}>
|
|
||||||
<HTMLRenderer purify={false}>{playIcon}</HTMLRenderer>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tags(): string | string[] {
|
tags(): string | string[] {
|
||||||
|
|
Loading…
Add table
Reference in a new issue