Made the BBCode renderer fully popoutable which now allows the PokeModal to be popoutable
parent
2755c1e62d
commit
126b836cbd
|
@ -27,6 +27,11 @@ import {server_connections} from "tc-shared/ConnectionManager";
|
||||||
import {spawnConnectModalNew} from "tc-shared/ui/modal/connect/Controller";
|
import {spawnConnectModalNew} from "tc-shared/ui/modal/connect/Controller";
|
||||||
import {initializeKeyControl} from "./KeyControl";
|
import {initializeKeyControl} from "./KeyControl";
|
||||||
import {assertMainApplication} from "tc-shared/ui/utils";
|
import {assertMainApplication} from "tc-shared/ui/utils";
|
||||||
|
import {clientServiceInvite} from "tc-shared/clientservice";
|
||||||
|
import {ActionResult} from "tc-services";
|
||||||
|
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
|
||||||
|
import {ErrorCode} from "tc-shared/connection/ErrorCode";
|
||||||
|
import {bookmarks} from "tc-shared/Bookmarks";
|
||||||
|
|
||||||
/* required import for init */
|
/* required import for init */
|
||||||
import "svg-sprites/client-icons";
|
import "svg-sprites/client-icons";
|
||||||
|
@ -49,11 +54,7 @@ import "./ui/elements/ContextDivider";
|
||||||
import "./ui/elements/Tab";
|
import "./ui/elements/Tab";
|
||||||
import "./clientservice";
|
import "./clientservice";
|
||||||
import "./text/bbcode/InviteController";
|
import "./text/bbcode/InviteController";
|
||||||
import {clientServiceInvite} from "tc-shared/clientservice";
|
import "./text/bbcode/YoutubeController";
|
||||||
import {ActionResult} from "tc-services";
|
|
||||||
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
|
|
||||||
import {ErrorCode} from "tc-shared/connection/ErrorCode";
|
|
||||||
import {bookmarks} from "tc-shared/Bookmarks";
|
|
||||||
|
|
||||||
assertMainApplication();
|
assertMainApplication();
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,9 @@ import {IpcInviteInfo} from "tc-shared/text/bbcode/InviteDefinitions";
|
||||||
import {LogCategory, logError} from "tc-shared/log";
|
import {LogCategory, logError} from "tc-shared/log";
|
||||||
import {clientServiceInvite, clientServices} from "tc-shared/clientservice";
|
import {clientServiceInvite, clientServices} from "tc-shared/clientservice";
|
||||||
import {handleConnectRequest} from "tc-shared/main";
|
import {handleConnectRequest} from "tc-shared/main";
|
||||||
|
import {assertMainApplication} from "tc-shared/ui/utils";
|
||||||
|
|
||||||
|
assertMainApplication();
|
||||||
|
|
||||||
let ipcChannel: IPCChannel;
|
let ipcChannel: IPCChannel;
|
||||||
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
|
|
|
@ -2,7 +2,6 @@ import * as React from "react";
|
||||||
import {IpcInviteInfo, IpcInviteInfoLoaded} from "tc-shared/text/bbcode/InviteDefinitions";
|
import {IpcInviteInfo, IpcInviteInfoLoaded} from "tc-shared/text/bbcode/InviteDefinitions";
|
||||||
import {ChannelMessage, getIpcInstance, IPCChannel} from "tc-shared/ipc/BrowserIPC";
|
import {ChannelMessage, getIpcInstance, IPCChannel} from "tc-shared/ipc/BrowserIPC";
|
||||||
import * as loader from "tc-loader";
|
import * as loader from "tc-loader";
|
||||||
import {AppParameters} from "tc-shared/settings";
|
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import _ = require("lodash");
|
import _ = require("lodash");
|
||||||
import {Translatable} from "tc-shared/ui/react-elements/i18n";
|
import {Translatable} from "tc-shared/ui/react-elements/i18n";
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import {ChannelMessage, getIpcInstance, IPCChannel} from "tc-shared/ipc/BrowserIPC";
|
||||||
|
import * as loader from "tc-loader";
|
||||||
|
import {global_client_actions} from "tc-shared/events/GlobalEvents";
|
||||||
|
import {assertMainApplication} from "tc-shared/ui/utils";
|
||||||
|
|
||||||
|
assertMainApplication();
|
||||||
|
|
||||||
|
let ipcChannel: IPCChannel;
|
||||||
|
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
|
name: "Invite controller init",
|
||||||
|
function: async () => {
|
||||||
|
ipcChannel = getIpcInstance().createChannel("bbcode-youtube");
|
||||||
|
ipcChannel.messageHandler = handleIpcMessage;
|
||||||
|
},
|
||||||
|
priority: 10
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function handleIpcMessage(remoteId: string, broadcast: boolean, message: ChannelMessage) {
|
||||||
|
if(message.type === "bbcode-youtube") {
|
||||||
|
global_client_actions.fire("action_w2g", {
|
||||||
|
videoUrl: message.data.videoUrl,
|
||||||
|
handlerId: message.data.handlerId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as loader from "tc-loader";
|
import * as loader from "tc-loader";
|
||||||
import {rendererReact, rendererText} from "tc-shared/text/bbcode/renderer";
|
import {BBCodeHandlerContext, rendererReact, rendererText} from "tc-shared/text/bbcode/renderer";
|
||||||
import {ElementRenderer} from "vendor/xbbcode/renderer/base";
|
import {ElementRenderer} from "vendor/xbbcode/renderer/base";
|
||||||
import {TagElement} from "vendor/xbbcode/elements";
|
import {TagElement} from "vendor/xbbcode/elements";
|
||||||
import {BBCodeRenderer} from "tc-shared/text/bbcode";
|
import {BBCodeRenderer} from "tc-shared/text/bbcode";
|
||||||
|
@ -8,11 +8,11 @@ import {HTMLRenderer} from "tc-shared/ui/react-elements/HTMLRenderer";
|
||||||
import * as contextmenu from "tc-shared/ui/elements/ContextMenu";
|
import * as contextmenu from "tc-shared/ui/elements/ContextMenu";
|
||||||
import {spawn_context_menu} from "tc-shared/ui/elements/ContextMenu";
|
import {spawn_context_menu} from "tc-shared/ui/elements/ContextMenu";
|
||||||
import {copyToClipboard} from "tc-shared/utils/helpers";
|
import {copyToClipboard} from "tc-shared/utils/helpers";
|
||||||
import {global_client_actions} from "tc-shared/events/GlobalEvents";
|
import {getIpcInstance, IPCChannel} from "tc-shared/ipc/BrowserIPC";
|
||||||
import {server_connections} from "tc-shared/ConnectionManager";
|
import {useContext} from "react";
|
||||||
|
|
||||||
const playIcon = require("./yt-play-button.svg");
|
const playIcon = require("./yt-play-button.svg");
|
||||||
const cssStyle = require("./youtube.scss");
|
const cssStyle = require("./YoutubeRenderer.scss");
|
||||||
|
|
||||||
const patternYtVideoId = /^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\/))([^?&"'>]{10,11})$/;
|
const patternYtVideoId = /^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\/))([^?&"'>]{10,11})$/;
|
||||||
let reactId = 0;
|
let reactId = 0;
|
||||||
|
@ -36,6 +36,8 @@ export const YoutubeRenderer = (props: { children?: React.ReactElement | React.R
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handlerId = useContext(BBCodeHandlerContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cssStyle.container}
|
className={cssStyle.container}
|
||||||
|
@ -43,12 +45,7 @@ export const YoutubeRenderer = (props: { children?: React.ReactElement | React.R
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
spawn_context_menu(event.pageX, event.pageY, {
|
spawn_context_menu(event.pageX, event.pageY, {
|
||||||
callback: () => {
|
callback: () => ipcChannel.sendMessage("w2g", { videoUrl: props.url, handlerId: handlerId }),
|
||||||
global_client_actions.fire("action_w2g", {
|
|
||||||
videoUrl: props.url,
|
|
||||||
handlerId: server_connections.getActiveConnectionHandler().handlerId
|
|
||||||
});
|
|
||||||
},
|
|
||||||
name: tr("Watch video"),
|
name: tr("Watch video"),
|
||||||
type: contextmenu.MenuEntryType.ENTRY,
|
type: contextmenu.MenuEntryType.ENTRY,
|
||||||
icon_class: ""
|
icon_class: ""
|
||||||
|
@ -69,22 +66,18 @@ export const YoutubeRenderer = (props: { children?: React.ReactElement | React.R
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img draggable={false} src={"https://img.youtube.com/vi/" + result[1] + "/hqdefault.jpg"} alt={"Video thumbnail"} title={tra("Youtube video {}", result[1])} />
|
<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={() => {
|
<button className={cssStyle.playButton} onClick={() => ipcChannel.sendMessage("w2g", { videoUrl: props.url, handlerId: handlerId })}>
|
||||||
global_client_actions.fire("action_w2g", {
|
|
||||||
videoUrl: props.url,
|
|
||||||
handlerId: server_connections.getActiveConnectionHandler().handlerId
|
|
||||||
});
|
|
||||||
}}>
|
|
||||||
<HTMLRenderer purify={false}>{playIcon}</HTMLRenderer>
|
<HTMLRenderer purify={false}>{playIcon}</HTMLRenderer>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ipcChannel: IPCChannel;
|
||||||
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 () => {
|
||||||
|
ipcChannel = getIpcInstance().createCoreControlChannel("bbcode-youtube");
|
||||||
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);
|
|
@ -1,8 +1,8 @@
|
||||||
import * as loader from "tc-loader";
|
import * as loader from "tc-loader";
|
||||||
|
import * as React from "react";
|
||||||
import { rendererReact } from "tc-shared/text/bbcode/renderer";
|
import { rendererReact } from "tc-shared/text/bbcode/renderer";
|
||||||
import {ElementRenderer} from "vendor/xbbcode/renderer/base";
|
import {ElementRenderer} from "vendor/xbbcode/renderer/base";
|
||||||
import {TextElement} from "vendor/xbbcode/elements";
|
import {TextElement} from "vendor/xbbcode/elements";
|
||||||
import * as React from "react";
|
|
||||||
import ReactRenderer from "vendor/xbbcode/renderer/react";
|
import ReactRenderer from "vendor/xbbcode/renderer/react";
|
||||||
import {Settings, settings} from "tc-shared/settings";
|
import {Settings, settings} from "tc-shared/settings";
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,11 @@ import * as DOMPurify from "dompurify";
|
||||||
import {copyToClipboard} from "tc-shared/utils/helpers";
|
import {copyToClipboard} from "tc-shared/utils/helpers";
|
||||||
import {rendererReact, rendererText} from "tc-shared/text/bbcode/renderer";
|
import {rendererReact, rendererText} from "tc-shared/text/bbcode/renderer";
|
||||||
import {MenuEntryType, spawn_context_menu} from "tc-shared/ui/elements/ContextMenu";
|
import {MenuEntryType, spawn_context_menu} from "tc-shared/ui/elements/ContextMenu";
|
||||||
|
|
||||||
import '!style-loader!css-loader!highlight.js/styles/darcula.css';
|
|
||||||
import {Settings, settings} from "tc-shared/settings";
|
import {Settings, settings} from "tc-shared/settings";
|
||||||
import {LogCategory, logWarn} from "tc-shared/log";
|
import {LogCategory, logWarn} from "tc-shared/log";
|
||||||
|
|
||||||
|
import '!style-loader!css-loader!highlight.js/styles/darcula.css';
|
||||||
|
|
||||||
const registerLanguage = (name, language: Promise<any>) => {
|
const registerLanguage = (name, language: Promise<any>) => {
|
||||||
language.then(lan => hljs.registerLanguage(name, lan.default)).catch(error => {
|
language.then(lan => hljs.registerLanguage(name, lan.default)).catch(error => {
|
||||||
logWarn(LogCategory.CHAT, tr("Failed to load language %s (%o)"), name, error);
|
logWarn(LogCategory.CHAT, tr("Failed to load language %s (%o)"), name, error);
|
||||||
|
|
|
@ -10,11 +10,9 @@ import HTMLRenderer from "vendor/xbbcode/renderer/html";
|
||||||
|
|
||||||
import "./emoji";
|
import "./emoji";
|
||||||
import "./highlight";
|
import "./highlight";
|
||||||
import "./youtube";
|
import "./YoutubeRenderer";
|
||||||
import "./url";
|
import "./url";
|
||||||
import "./image";
|
import "./image";
|
||||||
import {ElementRenderer, Renderer} from "vendor/xbbcode/renderer/base";
|
|
||||||
import {TextElement} from "vendor/xbbcode/elements";
|
|
||||||
|
|
||||||
export let BBCodeHandlerContext: Context<string>;
|
export let BBCodeHandlerContext: Context<string>;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +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";
|
import {isYoutubeLink, YoutubeRenderer} from "tc-shared/text/bbcode/YoutubeRenderer";
|
||||||
import {InviteLinkRenderer, isInviteLink} from "tc-shared/text/bbcode/InviteRenderer";
|
import {InviteLinkRenderer, isInviteLink} from "tc-shared/text/bbcode/InviteRenderer";
|
||||||
|
|
||||||
function spawnUrlContextMenu(pageX: number, pageY: number, target: string) {
|
function spawnUrlContextMenu(pageX: number, pageY: number, target: string) {
|
||||||
|
|
|
@ -32,6 +32,10 @@ html:root {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.window {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.pokeList {
|
.pokeList {
|
||||||
|
@ -73,7 +77,8 @@ html:root {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
margin-top: 1em;
|
margin-top: auto;
|
||||||
|
padding-top: 1em;
|
||||||
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
|
|
@ -19,7 +19,7 @@ const PokeRenderer = React.memo((props: { poke: PokeRecord }) => (
|
||||||
<div className={cssStyle.date}>{moment(props.poke.timestamp).format("HH:mm:ss")}</div> -
|
<div className={cssStyle.date}>{moment(props.poke.timestamp).format("HH:mm:ss")}</div> -
|
||||||
<ClientTag clientName={props.poke.clientName} clientUniqueId={props.poke.clientUniqueId} handlerId={props.poke.handlerId} className={cssStyle.user} />
|
<ClientTag clientName={props.poke.clientName} clientUniqueId={props.poke.clientUniqueId} handlerId={props.poke.handlerId} className={cssStyle.user} />
|
||||||
<div className={cssStyle.text}><Translatable>pokes you</Translatable></div>:
|
<div className={cssStyle.text}><Translatable>pokes you</Translatable></div>:
|
||||||
<div><BBCodeRenderer message={props.poke.message} settings={{ convertSingleUrls: true }} /></div>
|
<div><BBCodeRenderer message={props.poke.message} settings={{ convertSingleUrls: true }} handlerId={props.poke.handlerId} /></div>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class PokeModal extends AbstractModal {
|
||||||
renderBody(): React.ReactElement {
|
renderBody(): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
<VariablesContext.Provider value={this.variables}>
|
<VariablesContext.Provider value={this.variables}>
|
||||||
<div className={cssStyle.container}>
|
<div className={cssStyle.container + " " + (this.properties.windowed ? cssStyle.window : "")}>
|
||||||
<PokeListRenderer />
|
<PokeListRenderer />
|
||||||
<div className={cssStyle.buttons}>
|
<div className={cssStyle.buttons}>
|
||||||
<div className={cssStyle.spacer} />
|
<div className={cssStyle.spacer} />
|
||||||
|
|
|
@ -88,7 +88,6 @@ registerModal({
|
||||||
registerModal({
|
registerModal({
|
||||||
modalId: "modal-poked",
|
modalId: "modal-poked",
|
||||||
classLoader: async () => await import("tc-shared/ui/modal/poke/Renderer"),
|
classLoader: async () => await import("tc-shared/ui/modal/poke/Renderer"),
|
||||||
/* FIXME: Make popoutable after the bbcode renderer part has been made popoutable (currently not because of the youtube renderer) */
|
popoutSupported: true
|
||||||
popoutSupported: false
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue