2020-09-24 13:51:22 +00:00
|
|
|
import * as loader from "tc-loader";
|
|
|
|
import {Stage} from "tc-loader";
|
|
|
|
import {ConnectionHandler, ConnectionState} from "tc-shared/ConnectionHandler";
|
|
|
|
import * as React from "react";
|
2020-09-24 20:16:08 +00:00
|
|
|
import {useState} from "react";
|
2020-09-28 07:59:20 +00:00
|
|
|
import * as ReactDOM from "react-dom";
|
2020-09-24 13:51:22 +00:00
|
|
|
import {server_connections} from "tc-shared/ConnectionManager";
|
|
|
|
|
|
|
|
import {
|
|
|
|
ClientIcon,
|
|
|
|
spriteEntries as kClientSpriteEntries,
|
|
|
|
spriteUrl as kClientSpriteUrl
|
|
|
|
} from "svg-sprites/client-icons";
|
2020-09-28 07:59:20 +00:00
|
|
|
import {Registry} from "tc-shared/events";
|
|
|
|
|
|
|
|
interface FaviconEvents {
|
|
|
|
query_icon: {},
|
|
|
|
notify_icon: { icon: ClientIcon | undefined }
|
|
|
|
}
|
2020-09-24 13:51:22 +00:00
|
|
|
|
|
|
|
let iconImage: HTMLImageElement;
|
|
|
|
async function initializeFaviconRenderer() {
|
2020-09-28 07:59:20 +00:00
|
|
|
const events = new Registry<FaviconEvents>();
|
|
|
|
initializeFaviconController(events);
|
|
|
|
|
2020-09-24 13:51:22 +00:00
|
|
|
iconImage = new Image();
|
|
|
|
iconImage.src = kClientSpriteUrl;
|
2021-03-17 12:28:27 +00:00
|
|
|
|
2020-09-24 13:51:22 +00:00
|
|
|
await new Promise((resolve, reject) => {
|
|
|
|
iconImage.onload = resolve;
|
|
|
|
iconImage.onerror = () => reject("failed to load client icon sprite");
|
|
|
|
});
|
|
|
|
|
|
|
|
let container = document.createElement("span");
|
2020-09-28 07:59:20 +00:00
|
|
|
ReactDOM.render(ReactDOM.createPortal(<FaviconRenderer events={events} />, document.head), container, () => {
|
2020-09-24 13:51:22 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2020-09-28 07:59:20 +00:00
|
|
|
function initializeFaviconController(events: Registry<FaviconEvents>) {
|
|
|
|
let currentHandler: ConnectionHandler;
|
|
|
|
let currentEvents: (() => void)[] = [];
|
2020-09-24 13:51:22 +00:00
|
|
|
|
2020-09-28 07:59:20 +00:00
|
|
|
server_connections.events().on("notify_active_handler_changed", event => setCurrentHandler(event.newHandler));
|
2020-09-24 13:51:22 +00:00
|
|
|
|
2020-09-28 07:59:20 +00:00
|
|
|
const setCurrentHandler = (handler: ConnectionHandler) => {
|
|
|
|
finalizeCurrentHandler();
|
2020-09-28 08:50:40 +00:00
|
|
|
if(handler) {
|
|
|
|
initializeCurrentHandler(handler);
|
|
|
|
}
|
|
|
|
currentHandler = handler;
|
2020-09-28 07:59:20 +00:00
|
|
|
sendFavicon();
|
|
|
|
}
|
|
|
|
|
|
|
|
const initializeCurrentHandler = (handler: ConnectionHandler) => {
|
|
|
|
currentEvents.push(handler.events().on("notify_connection_state_changed", () => sendFavicon()));
|
|
|
|
currentEvents.push(handler.getClient().events.on("notify_status_icon_changed", () => sendFavicon()));
|
|
|
|
};
|
|
|
|
|
|
|
|
const finalizeCurrentHandler = () => {
|
|
|
|
currentEvents.forEach(callback => callback());
|
|
|
|
currentEvents = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
const sendFavicon = () => {
|
|
|
|
let icon: ClientIcon;
|
|
|
|
|
|
|
|
if(currentHandler?.connection_state === ConnectionState.CONNECTED) {
|
|
|
|
icon = currentHandler.getClient().getStatusIcon();
|
|
|
|
}
|
|
|
|
|
2020-11-07 12:16:07 +00:00
|
|
|
events.fire_later("notify_icon", { icon: icon })
|
2020-09-28 07:59:20 +00:00
|
|
|
};
|
|
|
|
|
2021-01-10 16:36:57 +00:00
|
|
|
setCurrentHandler(server_connections.getActiveConnectionHandler());
|
2020-09-28 07:59:20 +00:00
|
|
|
events.on("query_icon", () => sendFavicon());
|
|
|
|
}
|
2020-09-24 13:51:22 +00:00
|
|
|
|
|
|
|
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"}/>;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-09-28 07:59:20 +00:00
|
|
|
const FaviconRenderer = (props: { events: Registry<FaviconEvents> }) => {
|
|
|
|
const [ favicon, setFavicon ] = useState<ClientIcon>(() => {
|
|
|
|
props.events.fire("query_icon");
|
|
|
|
return undefined;
|
|
|
|
});
|
|
|
|
props.events.reactUse("notify_icon", event => setFavicon(event.icon));
|
2020-09-24 20:16:08 +00:00
|
|
|
|
2020-09-28 07:59:20 +00:00
|
|
|
if(!favicon) {
|
2020-09-24 13:51:22 +00:00
|
|
|
return <DefaultFaviconRenderer key={"default"} />;
|
2020-09-28 07:59:20 +00:00
|
|
|
} else {
|
2020-09-28 08:50:40 +00:00
|
|
|
return <ClientIconFaviconRenderer icon={favicon} key={"icon-" + favicon} />;
|
2020-09-24 13:51:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
|
|
|
|
name: "favicon renderer",
|
|
|
|
function: initializeFaviconRenderer,
|
|
|
|
priority: 10
|
|
|
|
});
|