TeaWeb/web/app/ui/FaviconRenderer.tsx
2020-09-24 22:16:08 +02:00

84 lines
No EOL
3.2 KiB
TypeScript

import * as loader from "tc-loader";
import {Stage} from "tc-loader";
import {ConnectionHandler, ConnectionState} from "tc-shared/ConnectionHandler";
import * as React from "react";
import * as ReactDOM from "react-dom";
import {useState} from "react";
import {server_connections} from "tc-shared/ConnectionManager";
import {
ClientIcon,
spriteEntries as kClientSpriteEntries,
spriteUrl as kClientSpriteUrl
} from "svg-sprites/client-icons";
let iconImage: HTMLImageElement;
async function initializeFaviconRenderer() {
iconImage = new Image();
iconImage.src = kClientSpriteUrl;
await new Promise((resolve, reject) => {
iconImage.onload = resolve;
iconImage.onerror = () => reject("failed to load client icon sprite");
});
let container = document.createElement("span");
ReactDOM.render(ReactDOM.createPortal(<FaviconRenderer />, document.head), container, () => {
document.getElementById("favicon").remove();
});
//container.remove();
}
function clientIconToDataUrl(icon: ClientIcon) : string | undefined {
const sprite = kClientSpriteEntries.find(e => e.className === icon);
if(!sprite) {
return;
}
const canvas = document.createElement("canvas");
canvas.width = sprite.width;
canvas.height = sprite.height;
const context = canvas.getContext("2d");
context.drawImage(iconImage, sprite.xOffset, sprite.yOffset, sprite.width, sprite.height, 0, 0, sprite.width, sprite.height);
return canvas.toDataURL();
}
const FaviconRenderer = () => {
const [ handler, setHandler ] = useState<ConnectionHandler>(server_connections.active_connection());
server_connections.events().reactUse("notify_active_handler_changed", event => setHandler(event.newHandler));
return handler ? <HandlerFaviconRenderer connection={handler} key={"handler-" + handler.handlerId} /> : <DefaultFaviconRenderer key={"default"} />;
};
const DefaultFaviconRenderer = () => <link key={"normal"} rel={"shortcut icon"} href={"img/favicon/teacup.png"} type={"image/x-icon"} />;
const ClientIconFaviconRenderer = (props: { icon: ClientIcon }) => {
const url = clientIconToDataUrl(props.icon);
if(!url) {
return <DefaultFaviconRenderer key={"broken"} />;
} else {
return <link key={"status"} rel={"shortcut icon"} href={url} type={"image/x-icon"}/>;
}
};
const HandlerFaviconRenderer = (props: { connection: ConnectionHandler }) => {
const [ showClientStatus, setShowClientStatus ] = useState(props.connection.connection_state === ConnectionState.CONNECTED);
props.connection.events().reactUse("notify_connection_state_changed", event => setShowClientStatus(event.new_state === ConnectionState.CONNECTED));
const [ statusIcon, setStatusIcon ] = useState<ClientIcon>(props.connection.getClient().getStatusIcon());
props.connection.getClient().events.reactUse("notify_status_icon_changed", event => setStatusIcon(event.newIcon));
if(showClientStatus) {
return <ClientIconFaviconRenderer icon={statusIcon} key={"server"} />;
} else {
return <DefaultFaviconRenderer key={"default"} />;
}
}
loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
name: "favicon renderer",
function: initializeFaviconRenderer,
priority: 10
});