Using react to render the image preview and removed the main app template
parent
4d2b83d7a3
commit
64b618d0bf
|
@ -188,7 +188,6 @@ function execute_build_debug() {
|
||||||
}
|
}
|
||||||
|
|
||||||
chmod +x ./scripts/build.sh
|
chmod +x ./scripts/build.sh
|
||||||
chmod +x ./scripts/web_package.sh
|
|
||||||
if [[ ${build_release} ]]; then
|
if [[ ${build_release} ]]; then
|
||||||
execute_build_release
|
execute_build_release
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -5,29 +5,6 @@
|
||||||
<title>TeaSpeak-Web client templates</title>
|
<title>TeaSpeak-Web client templates</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script class="jsrender-template" id="tmpl_main" type="text/html">
|
|
||||||
<div class="overlay-image-preview hidden" id="overlay-image-preview">
|
|
||||||
<div class="container-menu-bar">
|
|
||||||
<div class="entry button-open-in-window">
|
|
||||||
<div class="container-icon">
|
|
||||||
<img src="img/icon_image_preview_browse.svg">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Why would you like to download images?
|
|
||||||
<div class="entry button-download">
|
|
||||||
<div class="icon_em client-download"></div>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
<div class="entry button-close">
|
|
||||||
<div class="icon_em client-close_button"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="container-image">
|
|
||||||
<img src="" alt="image"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="template-group-modals">
|
<div class="template-group-modals">
|
||||||
<script class="jsrender-template" id="tmpl_modal" type="text/html">
|
<script class="jsrender-template" id="tmpl_modal" type="text/html">
|
||||||
<div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
<div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="16" enable-background="new 0 0 512.418 512.418" fill="#7289da" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m13.667 2.3463c-3.1281-3.1282-8.1918-3.1287-11.32 0-3.1282 3.1282-3.1287 8.1918 0 11.32 3.1281 3.1282 8.1917 3.1286 11.32 0 3.1282-3.1282 3.1287-8.1918 0-11.32zm-.33456 10.179c-.374-.33444-.77407-.6304-1.1958-.88547.27872-.96278.44384-2.0222.48287-3.1236h2.3534c-.10641 1.4845-.67678 2.877-1.6405 4.009zm-12.292-4.009h2.3534c.039 1.1013.20416 2.1608.48288 3.1236-.42169.25507-.82175.55103-1.1958.88547-.96375-1.132-1.5341-2.5246-1.6405-4.009zm1.6406-5.0293c.374.33444.77406.63041 1.1958.88547-.27872.96279-.44384 2.0223-.48288 3.1236h-2.3534c.10643-1.4844.67678-2.877 1.6406-4.009zm4.8155.99091c-.83193-.0595-1.6341-.26441-2.3778-.60244.4325-1.1137 1.2298-2.4495 2.3778-2.7805zm0 1.0221v1.996h-3.082c.0353-.93163.16731-1.8262.38684-2.6448.8451.36944 1.754.59006 2.6952.64872zm0 3.0162v1.996c-.94122.0587-1.8501.27928-2.6952.64872-.21953-.81853-.35153-1.7131-.38684-2.6448zm0 3.0182v3.3829c-1.1479-.33103-1.9452-1.6667-2.3778-2.7805.74366-.33803 1.5458-.54293 2.3778-.60243zm1.0202 0c.83194.0595 1.6341.2644 2.3777.60243-.43253 1.1138-1.2298 2.4495-2.3777 2.7805zm0-1.0221v-1.996h3.082c-.0353.93162-.16732 1.8262-.38685 2.6448-.84509-.36944-1.754-.59006-2.6952-.64872zm0-3.0162v-1.996c.94122-.0587 1.8501-.27928 2.6952-.64872.21953.81853.35153 1.7131.38685 2.6448zm0-3.0182v-3.3829c1.1479.33103 1.9452 1.6668 2.3777 2.7805-.74365.338-1.5458.54291-2.3777.60241zm2.2912-2.8737c.65297.28594 1.2622.67366 1.8083 1.1547-.25994.22919-.53422.437-.82063.62285-.25434-.62975-.57925-1.2418-.98763-1.7776zm-6.5903 1.7776c-.28641-.18585-.56066-.39366-.82063-.62285.54609-.48106 1.1553-.86878 1.8082-1.1547-.40837.53588-.73328 1.1479-.98762 1.7776zm3e-5 9.2487c.25431.62972.57928 1.2418.98762 1.7776-.65297-.28593-1.2622-.67365-1.8082-1.1547.25994-.22919.53422-.43701.82063-.62285zm7.5779 0c.28641.18584.56069.39366.82063.62281-.5461.48107-1.1553.86879-1.8083 1.1547.40835-.53575.73329-1.1478.98763-1.7775zm.82381-5.1344c-.039-1.1013-.20415-2.1608-.48287-3.1236.42169-.25507.82172-.55104 1.1958-.88547.96375 1.132 1.5341 2.5246 1.6405 4.009z" style="stroke-width:.03125"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -1 +0,0 @@
|
||||||
<svg id="Layer_1" fill="#7289da" enable-background="new 0 0 512.418 512.418" height="512" viewBox="0 0 512.418 512.418" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m437.335 75.082c-100.1-100.102-262.136-100.118-362.252 0-100.103 100.102-100.118 262.136 0 362.253 100.1 100.102 262.136 100.117 362.252 0 100.103-100.102 100.117-262.136 0-362.253zm-10.706 325.739c-11.968-10.702-24.77-20.173-38.264-28.335 8.919-30.809 14.203-64.712 15.452-99.954h75.309c-3.405 47.503-21.657 92.064-52.497 128.289zm-393.338-128.289h75.309c1.249 35.242 6.533 69.145 15.452 99.954-13.494 8.162-26.296 17.633-38.264 28.335-30.84-36.225-49.091-80.786-52.497-128.289zm52.498-160.936c11.968 10.702 24.77 20.173 38.264 28.335-8.919 30.809-14.203 64.712-15.452 99.954h-75.31c3.406-47.502 21.657-92.063 52.498-128.289zm154.097 31.709c-26.622-1.904-52.291-8.461-76.088-19.278 13.84-35.639 39.354-78.384 76.088-88.977zm0 32.708v63.873h-98.625c1.13-29.812 5.354-58.439 12.379-84.632 27.043 11.822 56.127 18.882 86.246 20.759zm0 96.519v63.873c-30.119 1.877-59.203 8.937-86.246 20.759-7.025-26.193-11.249-54.82-12.379-84.632zm0 96.581v108.254c-36.732-10.593-62.246-53.333-76.088-88.976 23.797-10.817 49.466-17.374 76.088-19.278zm32.646 0c26.622 1.904 52.291 8.461 76.088 19.278-13.841 35.64-39.354 78.383-76.088 88.976zm0-32.708v-63.873h98.625c-1.13 29.812-5.354 58.439-12.379 84.632-27.043-11.822-56.127-18.882-86.246-20.759zm0-96.519v-63.873c30.119-1.877 59.203-8.937 86.246-20.759 7.025 26.193 11.249 54.82 12.379 84.632zm0-96.581v-108.254c36.734 10.593 62.248 53.338 76.088 88.977-23.797 10.816-49.466 17.373-76.088 19.277zm73.32-91.957c20.895 9.15 40.389 21.557 57.864 36.951-8.318 7.334-17.095 13.984-26.26 19.931-8.139-20.152-18.536-39.736-31.604-56.882zm-210.891 56.882c-9.165-5.947-17.941-12.597-26.26-19.931 17.475-15.394 36.969-27.801 57.864-36.951-13.068 17.148-23.465 36.732-31.604 56.882zm.001 295.958c8.138 20.151 18.537 39.736 31.604 56.882-20.895-9.15-40.389-21.557-57.864-36.951 8.318-7.334 17.095-13.984 26.26-19.931zm242.494 0c9.165 5.947 17.942 12.597 26.26 19.93-17.475 15.394-36.969 27.801-57.864 36.951 13.067-17.144 23.465-36.729 31.604-56.881zm26.362-164.302c-1.249-35.242-6.533-69.146-15.452-99.954 13.494-8.162 26.295-17.633 38.264-28.335 30.84 36.225 49.091 80.786 52.497 128.289z"/></svg>
|
|
Before Width: | Height: | Size: 2.2 KiB |
|
@ -53,8 +53,6 @@ import {clientServiceInvite} from "tc-shared/clientservice";
|
||||||
import {ActionResult} from "tc-services";
|
import {ActionResult} from "tc-services";
|
||||||
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
|
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
|
||||||
import {ErrorCode} from "tc-shared/connection/ErrorCode";
|
import {ErrorCode} from "tc-shared/connection/ErrorCode";
|
||||||
|
|
||||||
import "./Bookmarks";
|
|
||||||
import {bookmarks} from "tc-shared/Bookmarks";
|
import {bookmarks} from "tc-shared/Bookmarks";
|
||||||
|
|
||||||
assertMainApplication();
|
assertMainApplication();
|
||||||
|
@ -568,19 +566,4 @@ loader.register_task(loader.Stage.LOADED, {
|
||||||
bookmarks.executeAutoConnect();
|
bookmarks.executeAutoConnect();
|
||||||
},
|
},
|
||||||
name: tr("bookmark auto connect")
|
name: tr("bookmark auto connect")
|
||||||
});
|
|
||||||
|
|
||||||
/* TODO: Remove this after the image preview has been rewritten into react */
|
|
||||||
loader.register_task(Stage.JAVASCRIPT_INITIALIZING,{
|
|
||||||
name: "app init",
|
|
||||||
function: async () => {
|
|
||||||
try {
|
|
||||||
$("body").append($("#tmpl_main").renderTag());
|
|
||||||
} catch(error) {
|
|
||||||
logError(LogCategory.GENERAL, error);
|
|
||||||
loader.critical_error(tr("Failed to setup main page!"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
priority: 100
|
|
||||||
});
|
});
|
|
@ -5,7 +5,7 @@ import * as loader from "tc-loader";
|
||||||
import {rendererReact, rendererText} from "tc-shared/text/bbcode/renderer";
|
import {rendererReact, rendererText} from "tc-shared/text/bbcode/renderer";
|
||||||
import * as contextmenu from "tc-shared/ui/elements/ContextMenu";
|
import * as contextmenu from "tc-shared/ui/elements/ContextMenu";
|
||||||
import {copyToClipboard} from "tc-shared/utils/helpers";
|
import {copyToClipboard} from "tc-shared/utils/helpers";
|
||||||
import * as image_preview from "tc-shared/ui/frames/image_preview";
|
import * as image_preview from "tc-shared/ui/frames/ImagePreview";
|
||||||
|
|
||||||
export const regexImage = /^(?:https?):(?:\/{1,3}|\\)[-a-zA-Z0-9:;,@#%&()~_?+=\/\\.]*$/g;
|
export const regexImage = /^(?:https?):(?:\/{1,3}|\\)[-a-zA-Z0-9:;,@#%&()~_?+=\/\\.]*$/g;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ function loadImageForElement(element: HTMLImageElement) {
|
||||||
icon_class: "client-copy"
|
icon_class: "client-copy"
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
parent.css("cursor", "pointer").on('click', () => image_preview.preview_image(proxiedURL, url));
|
parent.css("cursor", "pointer").on('click', () => image_preview.showImagePreview(proxiedURL, url));
|
||||||
}
|
}
|
||||||
|
|
||||||
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
|
|
|
@ -11,72 +11,72 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: Move this into the control bar? */
|
/* TODO: Move this into the control bar? */
|
||||||
.controlBar {
|
.controlBar {
|
||||||
z-index: 200;
|
z-index: 200;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
||||||
height: 2em;
|
height: 2em;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mainContainer {
|
.mainContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
|
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channelTreeAndSidebar {
|
.channelTreeAndSidebar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
min-height: 27em;
|
min-height: 27em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channelTree {
|
.channelTree {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
background: var(--channel-tree-background);
|
background: var(--channel-tree-background);
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sideBar {
|
.sideBar {
|
||||||
min-width: 350px;
|
min-width: 350px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.containerLog {
|
.containerLog {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -18,6 +18,7 @@ import {HostBannerUiEvents} from "tc-shared/ui/frames/HostBannerDefinitions";
|
||||||
import {AppUiEvents} from "tc-shared/ui/AppDefinitions";
|
import {AppUiEvents} from "tc-shared/ui/AppDefinitions";
|
||||||
import {ChannelTreeRenderer} from "tc-shared/ui/tree/Renderer";
|
import {ChannelTreeRenderer} from "tc-shared/ui/tree/Renderer";
|
||||||
import {ChannelTreeUIEvents} from "tc-shared/ui/tree/Definitions";
|
import {ChannelTreeUIEvents} from "tc-shared/ui/tree/Definitions";
|
||||||
|
import {ImagePreviewHook} from "tc-shared/ui/frames/ImagePreview";
|
||||||
|
|
||||||
const cssStyle = require("./AppRenderer.scss");
|
const cssStyle = require("./AppRenderer.scss");
|
||||||
const VideoFrame = React.memo((props: { events: Registry<AppUiEvents> }) => {
|
const VideoFrame = React.memo((props: { events: Registry<AppUiEvents> }) => {
|
||||||
|
@ -100,8 +101,10 @@ export const TeaAppMainView = (props: {
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
<FooterRenderer />
|
<FooterRenderer />
|
||||||
|
|
||||||
|
<ErrorBoundary>
|
||||||
|
<ImagePreviewHook />
|
||||||
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ConnectionHandlerList */
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
@import "../../../css/static/properties";
|
||||||
|
@import "../../../css/static/mixin";
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1000;
|
||||||
|
|
||||||
|
pointer-events: all;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
opacity: 1;
|
||||||
|
background-color: #000000EF;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include transition(ease-in-out .25s);
|
||||||
|
}
|
||||||
|
|
||||||
|
.containerMenuBar {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
top: .25em;
|
||||||
|
left: 0;
|
||||||
|
right: .25em;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.entry {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 2em;
|
||||||
|
|
||||||
|
margin: .25em;
|
||||||
|
padding: .15em;
|
||||||
|
|
||||||
|
border-radius: .125em;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.containerIcon {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #FFFFFF1F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.containerImage {
|
||||||
|
max-width: 90%;
|
||||||
|
max-height: 90%;
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
img {
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
|
min-height: 1em;
|
||||||
|
min-width: 1em;
|
||||||
|
|
||||||
|
max-height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
import * as loader from "tc-loader";
|
||||||
|
import React from "react";
|
||||||
|
import {joinClassList} from "tc-shared/ui/react-elements/Helper";
|
||||||
|
import {ClientIconRenderer} from "tc-shared/ui/react-elements/Icons";
|
||||||
|
import {ClientIcon} from "svg-sprites/client-icons";
|
||||||
|
import ReactDOM from "react-dom";
|
||||||
|
|
||||||
|
const cssStyle = require("./ImagePreview.scss");
|
||||||
|
|
||||||
|
const imagePreviewInstance = React.createRef<ImagePreview>();
|
||||||
|
class ImagePreview extends React.PureComponent<{}, {
|
||||||
|
imageUrl: string | undefined,
|
||||||
|
targetUrl: string | undefined
|
||||||
|
}> {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = { targetUrl: undefined, imageUrl: undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={joinClassList(cssStyle.overlay, (!this.state.imageUrl ? cssStyle.hidden : undefined))}
|
||||||
|
onClick={event => {
|
||||||
|
if(event.isDefaultPrevented()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.closePreview()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className={cssStyle.containerMenuBar}>
|
||||||
|
<div
|
||||||
|
className={cssStyle.entry}
|
||||||
|
onClick={() => {
|
||||||
|
const win = window.open(this.state.targetUrl, '_blank');
|
||||||
|
win.focus();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ClientIconRenderer icon={ClientIcon.ImagePreviewBrowse} />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={cssStyle.entry}
|
||||||
|
onClick={() => this.closePreview()}
|
||||||
|
>
|
||||||
|
<ClientIconRenderer icon={ClientIcon.CloseButton} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={cssStyle.containerImage}>
|
||||||
|
<img src={this.state.imageUrl} title={this.state.targetUrl} alt={null} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
closePreview() {
|
||||||
|
this.setState({ imageUrl: undefined, targetUrl: undefined });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ImagePreviewHook = React.memo(() => {
|
||||||
|
return <ImagePreview ref={imagePreviewInstance} />;
|
||||||
|
})
|
||||||
|
|
||||||
|
export function showImagePreview(url: string, originalUrl: string) {
|
||||||
|
imagePreviewInstance.current?.setState({
|
||||||
|
imageUrl: url,
|
||||||
|
targetUrl: originalUrl
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isImagePreviewAvailable() {
|
||||||
|
return !!imagePreviewInstance.current;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function closeImagePreview() {
|
||||||
|
imagePreviewInstance.current?.closePreview();
|
||||||
|
}
|
|
@ -1,81 +0,0 @@
|
||||||
import * as loader from "tc-loader";
|
|
||||||
|
|
||||||
let preview_overlay: JQuery<HTMLDivElement>;
|
|
||||||
let container_image: JQuery<HTMLDivElement>;
|
|
||||||
let button_open_in_browser: JQuery;
|
|
||||||
|
|
||||||
export function preview_image(url: string, original_url: string) {
|
|
||||||
if(!preview_overlay) return;
|
|
||||||
|
|
||||||
container_image.empty();
|
|
||||||
$.spawn("img").attr({
|
|
||||||
"src": url,
|
|
||||||
"title": original_url,
|
|
||||||
"x-original-src": original_url
|
|
||||||
}).appendTo(container_image);
|
|
||||||
|
|
||||||
preview_overlay.removeClass("hidden");
|
|
||||||
button_open_in_browser.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function preview_image_tag(tag: JQuery) {
|
|
||||||
if(!preview_overlay) return;
|
|
||||||
|
|
||||||
container_image.empty();
|
|
||||||
container_image.append(tag);
|
|
||||||
|
|
||||||
preview_overlay.removeClass("hidden");
|
|
||||||
button_open_in_browser.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function current_url() {
|
|
||||||
const image_tag = container_image.find("img");
|
|
||||||
return image_tag.attr("x-original-src") || image_tag.attr("src") || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
export function close_preview() {
|
|
||||||
preview_overlay.addClass("hidden");
|
|
||||||
}
|
|
||||||
|
|
||||||
loader.register_task(loader.Stage.LOADED, {
|
|
||||||
priority: 0,
|
|
||||||
name: "image preview init",
|
|
||||||
function: async () => {
|
|
||||||
preview_overlay = $("#overlay-image-preview");
|
|
||||||
container_image = preview_overlay.find(".container-image") as any;
|
|
||||||
|
|
||||||
preview_overlay.find("img").on('click', event => event.preventDefault());
|
|
||||||
preview_overlay.on('click', event => {
|
|
||||||
if(event.isDefaultPrevented()) return;
|
|
||||||
close_preview();
|
|
||||||
});
|
|
||||||
|
|
||||||
preview_overlay.find(".button-close").on('click', event => {
|
|
||||||
event.preventDefault();
|
|
||||||
close_preview();
|
|
||||||
});
|
|
||||||
|
|
||||||
preview_overlay.find(".button-download").on('click', event => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = current_url();
|
|
||||||
link.target = "_blank";
|
|
||||||
|
|
||||||
const findex = link.href.lastIndexOf("/") + 1;
|
|
||||||
link.download = link.href.substr(findex);
|
|
||||||
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
});
|
|
||||||
|
|
||||||
button_open_in_browser = preview_overlay.find(".button-open-in-window");
|
|
||||||
button_open_in_browser.on('click', event => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
const win = window.open(current_url(), '_blank');
|
|
||||||
win.focus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
MusicBotUiEvents
|
MusicBotUiEvents
|
||||||
} from "tc-shared/ui/frames/side/MusicBotDefinitions";
|
} from "tc-shared/ui/frames/side/MusicBotDefinitions";
|
||||||
import {Translatable} from "tc-shared/ui/react-elements/i18n";
|
import {Translatable} from "tc-shared/ui/react-elements/i18n";
|
||||||
import {preview_image} from "tc-shared/ui/frames/image_preview";
|
import {showImagePreview} from "tc-shared/ui/frames/ImagePreview";
|
||||||
import {Slider} from "tc-shared/ui/react-elements/Slider";
|
import {Slider} from "tc-shared/ui/react-elements/Slider";
|
||||||
|
|
||||||
const cssStyle = require("./MusicBotRenderer.scss");
|
const cssStyle = require("./MusicBotRenderer.scss");
|
||||||
|
@ -144,7 +144,7 @@ const Thumbnail = React.memo(() => {
|
||||||
draggable={false}
|
draggable={false}
|
||||||
key={"song-thumbnail"}
|
key={"song-thumbnail"}
|
||||||
src={info.thumbnail}
|
src={info.thumbnail}
|
||||||
onClick={() => preview_image(info.thumbnail, info.thumbnail)}
|
onClick={() => showImagePreview(info.thumbnail, info.thumbnail)}
|
||||||
alt={tr("Thumbnail")}
|
alt={tr("Thumbnail")}
|
||||||
style={{ cursor: "pointer" }}
|
style={{ cursor: "pointer" }}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
import {Button} from "tc-shared/ui/react-elements/Button";
|
import {Button} from "tc-shared/ui/react-elements/Button";
|
||||||
import {Translatable} from "tc-shared/ui/react-elements/i18n";
|
import {Translatable} from "tc-shared/ui/react-elements/i18n";
|
||||||
import {LoadingDots} from "tc-shared/ui/react-elements/LoadingDots";
|
import {LoadingDots} from "tc-shared/ui/react-elements/LoadingDots";
|
||||||
import {preview_image} from "tc-shared/ui/frames/image_preview";
|
import {showImagePreview} from "tc-shared/ui/frames/ImagePreview";
|
||||||
import {joinClassList, useTr} from "tc-shared/ui/react-elements/Helper";
|
import {joinClassList, useTr} from "tc-shared/ui/react-elements/Helper";
|
||||||
import {spawnContextMenu} from "tc-shared/ui/ContextMenu";
|
import {spawnContextMenu} from "tc-shared/ui/ContextMenu";
|
||||||
import {copyToClipboard} from "tc-shared/utils/helpers";
|
import {copyToClipboard} from "tc-shared/utils/helpers";
|
||||||
|
@ -87,7 +87,7 @@ const PlaylistEntry = React.memo((props: { serverUniqueId: string, playlistId: n
|
||||||
draggable={false}
|
draggable={false}
|
||||||
key={"song-thumbnail"}
|
key={"song-thumbnail"}
|
||||||
src={status.thumbnailImage}
|
src={status.thumbnailImage}
|
||||||
onClick={() => preview_image(status.thumbnailImage, status.thumbnailImage)}
|
onClick={() => showImagePreview(status.thumbnailImage, status.thumbnailImage)}
|
||||||
alt={useTr("Thumbnail")}
|
alt={useTr("Thumbnail")}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import {ClientAvatar, kDefaultAvatarImage, kLoadingAvatarImage} from "tc-shared/file/Avatars";
|
import {ClientAvatar, kDefaultAvatarImage, kLoadingAvatarImage} from "tc-shared/file/Avatars";
|
||||||
import * as image_preview from "tc-shared/ui/frames/image_preview";
|
import * as image_preview from "tc-shared/ui/frames/ImagePreview";
|
||||||
|
|
||||||
const ImageStyle = { height: "100%", width: "100%", cursor: "pointer" };
|
const ImageStyle = { height: "100%", width: "100%", cursor: "pointer" };
|
||||||
export const AvatarRenderer = React.memo((props: { avatar: ClientAvatar | "loading" | "default", className?: string, alt?: string }) => {
|
export const AvatarRenderer = React.memo((props: { avatar: ClientAvatar | "loading" | "default", className?: string, alt?: string }) => {
|
||||||
|
@ -28,7 +28,7 @@ export const AvatarRenderer = React.memo((props: { avatar: ClientAvatar | "loadi
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
image_preview.preview_image(imageUrl, undefined);
|
image_preview.showImagePreview(imageUrl, undefined);
|
||||||
}}
|
}}
|
||||||
draggable={false}
|
draggable={false}
|
||||||
/>;
|
/>;
|
||||||
|
@ -46,7 +46,7 @@ export const AvatarRenderer = React.memo((props: { avatar: ClientAvatar | "loadi
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
image_preview.preview_image(imageUrl, undefined);
|
image_preview.showImagePreview(imageUrl, undefined);
|
||||||
}}
|
}}
|
||||||
draggable={false}
|
draggable={false}
|
||||||
/>;
|
/>;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -16,6 +16,7 @@
|
||||||
z-index: 201;
|
z-index: 201;
|
||||||
|
|
||||||
font-family: Arial, serif;
|
font-family: Arial, serif;
|
||||||
|
z-index: 10000;
|
||||||
|
|
||||||
> .containerMenuItem {
|
> .containerMenuItem {
|
||||||
> .menuItem {
|
> .menuItem {
|
||||||
|
|
Loading…
Reference in New Issue