From d1efa2ba3183dcd781178224b2e1da573916e923 Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Sat, 26 Sep 2020 01:22:21 +0200 Subject: [PATCH] Adjusted to the new icon API --- shared/js/ConnectionHandler.ts | 4 ++ shared/js/main.tsx | 2 + shared/js/tree/Channel.ts | 4 +- shared/js/ui/frames/MenuBar.ts | 16 +++-- shared/js/ui/frames/chat_frame.ts | 19 +++-- .../connection-handler-list/Controller.ts | 11 +-- .../connection-handler-list/Definitions.ts | 4 +- .../connection-handler-list/Renderer.tsx | 7 +- shared/js/ui/frames/control-bar/dropdown.tsx | 14 ++-- shared/js/ui/frames/control-bar/index.tsx | 3 +- .../ui/frames/log/DispatcherNotifications.ts | 10 ++- shared/js/ui/frames/side/client_info.ts | 5 +- shared/js/ui/modal/ModalBookmarks.ts | 7 +- shared/js/ui/modal/ModalClientInfo.ts | 4 +- shared/js/ui/modal/ModalConnect.ts | 6 +- shared/js/ui/modal/ModalCreateChannel.ts | 10 +-- shared/js/ui/modal/ModalGroupAssignment.ts | 3 +- shared/js/ui/modal/ModalIconSelect.ts | 29 ++++---- shared/js/ui/modal/ModalServerEdit.ts | 7 +- .../ui/modal/permission/PermissionEditor.tsx | 8 ++- shared/js/ui/modal/permission/TabHandler.tsx | 12 ++-- shared/js/ui/react-elements/Icon.tsx | 72 ++++++++----------- shared/js/ui/tree/Channel.tsx | 35 +++++---- shared/js/ui/tree/Client.tsx | 28 +++++--- shared/js/ui/tree/Server.tsx | 8 ++- shared/js/ui/tree/TreeEntry.tsx | 3 +- shared/js/ui/tree/View.tsx | 1 - 27 files changed, 185 insertions(+), 147 deletions(-) diff --git a/shared/js/ConnectionHandler.ts b/shared/js/ConnectionHandler.ts index 1c8c8047..5916e32f 100644 --- a/shared/js/ConnectionHandler.ts +++ b/shared/js/ConnectionHandler.ts @@ -1159,6 +1159,10 @@ export class ConnectionHandler { this.getVoiceRecorder()?.input?.setFilterMode(FilterMode.Filter); this.update_voice_status(); } + + getCurrentServerUniqueId() { + return this.channelTree.server.properties.virtualserver_unique_identifier; + } } export type ConnectionStateUpdateType = "microphone" | "speaker" | "away" | "subscribe" | "query"; diff --git a/shared/js/main.tsx b/shared/js/main.tsx index a065a447..b7046fb1 100644 --- a/shared/js/main.tsx +++ b/shared/js/main.tsx @@ -43,6 +43,8 @@ import {ConnectRequestData} from "tc-shared/ipc/ConnectHandler"; import "./video-viewer/Controller"; import "./profiles/ConnectionProfile"; import "./update/UpdaterWeb"; +import "./file/LocalIcons"; + import {defaultConnectProfile, findConnectProfile} from "tc-shared/profiles/ConnectionProfile"; import {server_connections} from "tc-shared/ConnectionManager"; import {initializeConnectionUIList} from "tc-shared/ui/frames/connection-handler-list/Controller"; diff --git a/shared/js/tree/Channel.ts b/shared/js/tree/Channel.ts index 3d107577..436484c1 100644 --- a/shared/js/tree/Channel.ts +++ b/shared/js/tree/Channel.ts @@ -740,8 +740,10 @@ export class ChannelEntry extends ChannelTreeEntry { } set collapsed(flag: boolean) { - if(this._flag_collapsed === flag) + if(this._flag_collapsed === flag) { return; + } + this._flag_collapsed = flag; this.events.fire("notify_collapsed_state_changed", { collapsed: flag }); this.view.current?.forceUpdate(); diff --git a/shared/js/ui/frames/MenuBar.ts b/shared/js/ui/frames/MenuBar.ts index beb6288b..77dc4ecf 100644 --- a/shared/js/ui/frames/MenuBar.ts +++ b/shared/js/ui/frames/MenuBar.ts @@ -20,10 +20,11 @@ import {spawnAbout} from "../../ui/modal/ModalAbout"; import * as loader from "tc-loader"; import {formatMessage} from "../../ui/frames/chat"; import {control_bar_instance} from "../../ui/frames/control-bar"; -import {icon_cache_loader, IconManager, LocalIcon} from "../../file/Icons"; +import {icon_cache_loader, IconManager, LocalIcon} from "../../file/IconsOld"; import {spawnPermissionEditorModal} from "../../ui/modal/permission/ModalPermissionEditor"; import {global_client_actions} from "tc-shared/events/GlobalEvents"; import {server_connections} from "tc-shared/ConnectionManager"; +import {generateIconJQueryTag, getIconManager, RemoteIcon} from "tc-shared/file/Icons"; export interface HRItem { } @@ -33,7 +34,7 @@ export interface MenuItem { delete_item(item: MenuItem | HRItem); items() : (MenuItem | HRItem)[]; - icon(klass?: string | LocalIcon) : string; //FIXME: Native client must work as well! + icon(klass?: string | RemoteIcon) : string; label(value?: string) : string; visible(value?: boolean) : boolean; disabled(value?: boolean) : boolean; @@ -179,12 +180,13 @@ namespace html { return this; } - icon(klass?: string | LocalIcon): string { + icon(klass?: string | RemoteIcon): string { this._label_icon_tag.children().remove(); - if(typeof(klass) === "string") + if(typeof(klass) === "string") { $.spawn("div").addClass("icon_em " + klass).appendTo(this._label_icon_tag); - else - IconManager.generate_tag(klass).appendTo(this._label_icon_tag); + } else { + generateIconJQueryTag(klass).appendTo(this._label_icon_tag); + } return ""; } @@ -290,7 +292,7 @@ export function rebuild_bookmarks() { const bookmark = entry as Bookmark; const item = root.append_item(bookmark.display_name); - item.icon(icon_cache_loader.load_icon(bookmark.last_icon_id, bookmark.last_icon_server_id)); + item.icon(getIconManager().resolveIcon(bookmark.last_icon_id, bookmark.last_icon_server_id)); item.click(() => boorkmak_connect(bookmark)); } }; diff --git a/shared/js/ui/frames/chat_frame.ts b/shared/js/ui/frames/chat_frame.ts index 07bb0569..d324f6dd 100644 --- a/shared/js/ui/frames/chat_frame.ts +++ b/shared/js/ui/frames/chat_frame.ts @@ -9,6 +9,7 @@ import {ClientInfo} from "../../ui/frames/side/client_info"; import {MusicInfo} from "../../ui/frames/side/music_info"; import {ConversationManager} from "../../ui/frames/side/ConversationManager"; import {PrivateConversationManager} from "../../ui/frames/side/PrivateConversationManager"; +import {generateIconJQueryTag, getIconManager} from "tc-shared/file/Icons"; export enum InfoFrameMode { NONE = "none", @@ -126,8 +127,10 @@ export class InfoFrame { html_tag.children().remove(); if(channel) { - if(channel.properties.channel_icon_id != 0) - client.handle.fileManager.icons.generateTag(channel.properties.channel_icon_id).appendTo(html_tag); + if(channel.properties.channel_icon_id != 0) { + const connection = channel.channelTree.client; + generateIconJQueryTag(getIconManager().resolveIcon(channel.properties.channel_icon_id, connection.getCurrentServerUniqueId(), connection.handlerId)).appendTo(html_tag); + } $.spawn("div").text(channel.formattedChannelName()).appendTo(html_tag); this.update_channel_limit(channel, html_limit_tag); @@ -154,8 +157,10 @@ export class InfoFrame { /* initialize */ if(channel) { - if(channel.properties.channel_icon_id != 0) - this.handle.handle.fileManager.icons.generateTag(channel.properties.channel_icon_id).appendTo(html_tag); + if(channel.properties.channel_icon_id != 0) { + const connection = channel.channelTree.client; + generateIconJQueryTag(getIconManager().resolveIcon(channel.properties.channel_icon_id, connection.getCurrentServerUniqueId(), connection.handlerId)).appendTo(html_tag); + } $.spawn("div").text(channel.formattedChannelName()).appendTo(html_tag); this.update_channel_limit(channel, html_limit_tag); @@ -163,8 +168,10 @@ export class InfoFrame { html_tag.append(formatMessage(tr("Unknown channel id {}"), current_channel_id)); } else if(channel_tree && current_channel_id == 0) { const server = this.handle.handle.channelTree.server; - if(server.properties.virtualserver_icon_id != 0) - this.handle.handle.fileManager.icons.generateTag(server.properties.virtualserver_icon_id).appendTo(html_tag); + if(server.properties.virtualserver_icon_id != 0) { + const connection = server.channelTree.client; + generateIconJQueryTag(getIconManager().resolveIcon(server.properties.virtualserver_icon_id, connection.getCurrentServerUniqueId(), connection.handlerId)).appendTo(html_tag); + } $.spawn("div").text(server.properties.virtualserver_name).appendTo(html_tag); html_tag_title.text(tr("You're chatting in Server")); diff --git a/shared/js/ui/frames/connection-handler-list/Controller.ts b/shared/js/ui/frames/connection-handler-list/Controller.ts index 1e0530e6..657f9d75 100644 --- a/shared/js/ui/frames/connection-handler-list/Controller.ts +++ b/shared/js/ui/frames/connection-handler-list/Controller.ts @@ -6,7 +6,8 @@ import {ConnectionHandlerList} from "tc-shared/ui/frames/connection-handler-list import {server_connections} from "tc-shared/ConnectionManager"; import {LogCategory, logWarn} from "tc-shared/log"; import {ConnectionState} from "tc-shared/ConnectionHandler"; -import {LocalIcon} from "tc-shared/file/Icons"; +import {LocalIcon} from "../../../file/IconsOld"; +import {RemoteIconInfo} from "tc-shared/file/Icons"; export function initializeConnectionUIList() { const container = document.getElementById("connection-handler-list"); @@ -119,19 +120,13 @@ function initializeController(events: Registry) { break; } - let icon: LocalIcon | undefined; - let iconId = handler.channelTree.server.properties.virtualserver_icon_id; - if(iconId !== 0) { - icon = handler.fileManager.icons.load_icon(handler.channelTree.server.properties.virtualserver_icon_id); - } - events.fire_async("notify_handler_status", { handlerId: event.handlerId, status: { handlerName: handler.channelTree.server.properties.virtualserver_name, connectionState: state, voiceReplaying: handler.getServerConnection().getVoiceConnection().isReplayingVoice(), - serverIcon: icon + serverIcon: { iconId: handler.channelTree.server.properties.virtualserver_icon_id, serverUniqueId: handler.getCurrentServerUniqueId() } } }); }); diff --git a/shared/js/ui/frames/connection-handler-list/Definitions.ts b/shared/js/ui/frames/connection-handler-list/Definitions.ts index b4121ada..becfc17b 100644 --- a/shared/js/ui/frames/connection-handler-list/Definitions.ts +++ b/shared/js/ui/frames/connection-handler-list/Definitions.ts @@ -1,4 +1,4 @@ -import {LocalIcon} from "tc-shared/file/Icons"; +import {RemoteIconInfo} from "tc-shared/file/Icons"; export type MouseMoveCoordinates = { x: number, y: number, xOffset: number }; export type HandlerConnectionState = "disconnected" | "connecting" | "connected"; @@ -7,7 +7,7 @@ export type HandlerStatus = { connectionState: HandlerConnectionState, handlerName: string, voiceReplaying: boolean, - serverIcon: LocalIcon | undefined + serverIcon: RemoteIconInfo | undefined } export interface ConnectionListUIEvents { diff --git a/shared/js/ui/frames/connection-handler-list/Renderer.tsx b/shared/js/ui/frames/connection-handler-list/Renderer.tsx index fd3a7a14..327cfba4 100644 --- a/shared/js/ui/frames/connection-handler-list/Renderer.tsx +++ b/shared/js/ui/frames/connection-handler-list/Renderer.tsx @@ -6,13 +6,14 @@ import { } from "tc-shared/ui/frames/connection-handler-list/Definitions"; import * as React from "react"; import {useContext, useEffect, useRef, useState} from "react"; -import {IconRenderer, LocalIconRenderer} from "tc-shared/ui/react-elements/Icon"; +import {IconRenderer, LocalIconRenderer, RemoteIconRenderer} from "tc-shared/ui/react-elements/Icon"; import {ClientIcon} from "svg-sprites/client-icons"; import {Translatable} from "tc-shared/ui/react-elements/i18n"; import {LoadingDots} from "tc-shared/ui/react-elements/LoadingDots"; import ResizeObserver from 'resize-observer-polyfill'; import {LogCategory, logWarn} from "tc-shared/log"; import {ClientIconRenderer} from "tc-shared/ui/react-elements/Icons"; +import {getIconManager} from "tc-shared/file/Icons"; const cssStyle = require("./Renderer.scss"); const Events = React.createContext>(undefined); @@ -46,9 +47,7 @@ const ConnectionHandler = React.memo((props: { handlerId: string, mode: Connecti cutoffName = status.handlerName.length > 30; voiceReplaying = status.voiceReplaying; displayedName = {status.handlerName}; - if(status.serverIcon) { - icon = ; - } + icon = ; break; case "connecting": diff --git a/shared/js/ui/frames/control-bar/dropdown.tsx b/shared/js/ui/frames/control-bar/dropdown.tsx index 88bd44d4..5c9c7515 100644 --- a/shared/js/ui/frames/control-bar/dropdown.tsx +++ b/shared/js/ui/frames/control-bar/dropdown.tsx @@ -1,11 +1,11 @@ import * as React from "react"; import {ReactComponentBase} from "tc-shared/ui/react-elements/ReactComponentBase"; -import {IconRenderer} from "tc-shared/ui/react-elements/Icon"; -import {LocalIcon} from "tc-shared/file/Icons"; +import {IconRenderer, RemoteIconRenderer} from "tc-shared/ui/react-elements/Icon"; +import {getIconManager, RemoteIconInfo} from "tc-shared/file/Icons"; const cssStyle = require("./button.scss"); export interface DropdownEntryProperties { - icon?: string | LocalIcon; + icon?: string | RemoteIconInfo; text: JSX.Element | string; onClick?: (event) => void; @@ -19,7 +19,9 @@ export class DropdownEntry extends ReactComponentBase - + {typeof this.props.icon === "string" ? : + + } {this.props.text}
@@ -30,7 +32,9 @@ export class DropdownEntry extends ReactComponentBase - + {typeof this.props.icon === "string" ? : + + } {this.props.text}
); diff --git a/shared/js/ui/frames/control-bar/index.tsx b/shared/js/ui/frames/control-bar/index.tsx index 88d86774..409f2803 100644 --- a/shared/js/ui/frames/control-bar/index.tsx +++ b/shared/js/ui/frames/control-bar/index.tsx @@ -22,7 +22,6 @@ import { import * as contextmenu from "tc-shared/ui/elements/ContextMenu"; import {createInputModal} from "tc-shared/ui/elements/Modal"; import {global_client_actions} from "tc-shared/events/GlobalEvents"; -import {icon_cache_loader} from "tc-shared/file/Icons"; import {ConnectionManagerEvents, server_connections} from "tc-shared/ConnectionManager"; const cssStyle = require("./index.scss"); @@ -121,7 +120,7 @@ class BookmarkButton extends ReactComponentBase<{ event_registry: Registry diff --git a/shared/js/ui/frames/log/DispatcherNotifications.ts b/shared/js/ui/frames/log/DispatcherNotifications.ts index aadd0040..296146ca 100644 --- a/shared/js/ui/frames/log/DispatcherNotifications.ts +++ b/shared/js/ui/frames/log/DispatcherNotifications.ts @@ -10,6 +10,7 @@ import {findLogDispatcher} from "../../../ui/frames/log/DispatcherLog"; import {formatDate} from "../../../MessageFormatter"; import {Settings, settings} from "../../../settings"; import {server_connections} from "tc-shared/ConnectionManager"; +import {getIconManager} from "tc-shared/file/Icons"; export type DispatcherLog = (data: TypeInfo[T], handlerId: string, eventType: T) => void; @@ -58,9 +59,12 @@ async function resolveServerIconUrl(handlerId: string) { const connection = server_connections.findConnection(handlerId); if(connection.channelTree.server.properties.virtualserver_icon_id) { - const icon = connection.fileManager.icons.load_icon(connection.channelTree.server.properties.virtualserver_icon_id); - await icon.await_loading(); - return icon.loaded_url; + const icon = getIconManager().resolveIcon(connection.channelTree.server.properties.virtualserver_icon_id, connection.getCurrentServerUniqueId(), connection.handlerId); + await icon.awaitLoaded(); + + if(icon.getState() === "loaded" && icon.iconId > 1000) { + return icon.getImageUrl(); + } } return kDefaultIcon; diff --git a/shared/js/ui/frames/side/client_info.ts b/shared/js/ui/frames/side/client_info.ts index d0e52d72..1628141a 100644 --- a/shared/js/ui/frames/side/client_info.ts +++ b/shared/js/ui/frames/side/client_info.ts @@ -6,6 +6,7 @@ import * as image_preview from "../image_preview"; import * as i18nc from "../../../i18n/country"; import {ClientEntry, LocalClientEntry} from "../../../tree/Client"; import {format_online_time} from "../../../utils/TimeUtils"; +import {generateIconJQueryTag, getIconManager} from "tc-shared/file/Icons"; export class ClientInfo { readonly handle: Frame; @@ -246,7 +247,7 @@ export class ClientInfo { container_groups.append( $.spawn("div").addClass("group-container") .append( - this.handle.handle.fileManager.icons.generateTag(group.properties.iconid) + generateIconJQueryTag(getIconManager().resolveIcon(group.properties.iconid, this.handle.handle.getCurrentServerUniqueId(), this.handle.handle.handlerId)) ).append( $.spawn("a").text(group.name).attr("title", tr("Group id: ") + group.id) ) @@ -265,7 +266,7 @@ export class ClientInfo { container_group.append( $.spawn("div").addClass("group-container") .append( - this.handle.handle.fileManager.icons.generateTag(group.properties.iconid) + generateIconJQueryTag(getIconManager().resolveIcon(group.properties.iconid, this.handle.handle.getCurrentServerUniqueId(), this.handle.handle.handlerId)) ).append( $.spawn("a").text(group.name).attr("title", tr("Group id: ") + group_id) ) diff --git a/shared/js/ui/modal/ModalBookmarks.ts b/shared/js/ui/modal/ModalBookmarks.ts index 24ddcda1..a4474909 100644 --- a/shared/js/ui/modal/ModalBookmarks.ts +++ b/shared/js/ui/modal/ModalBookmarks.ts @@ -20,7 +20,8 @@ import * as i18nc from "../../i18n/country"; import {formatMessage} from "../../ui/frames/chat"; import * as top_menu from "../frames/MenuBar"; import {control_bar_instance} from "../../ui/frames/control-bar"; -import {icon_cache_loader, IconManager} from "../../file/Icons"; +import {icon_cache_loader, IconManager} from "../../file/IconsOld"; +import {generateIconJQueryTag, getIconManager} from "tc-shared/file/Icons"; export function spawnBookmarkModal() { let modal: Modal; @@ -153,8 +154,8 @@ export function spawnBookmarkModal() { if (entry.type === BookmarkType.ENTRY) { const bookmark = entry as Bookmark; container.append( - bookmark.last_icon_id ? - IconManager.generate_tag(icon_cache_loader.load_icon(bookmark.last_icon_id, bookmark.last_icon_server_id), {animate: false}) : + bookmark.last_icon_id && bookmark.last_icon_server_id ? + generateIconJQueryTag(getIconManager().resolveIcon(bookmark.last_icon_id, bookmark.last_icon_server_id), {animate: false}) : $.spawn("div").addClass("icon-container icon_em") ); } else { diff --git a/shared/js/ui/modal/ModalClientInfo.ts b/shared/js/ui/modal/ModalClientInfo.ts index a756eb0e..e00c86a0 100644 --- a/shared/js/ui/modal/ModalClientInfo.ts +++ b/shared/js/ui/modal/ModalClientInfo.ts @@ -6,6 +6,7 @@ import * as i18nc from "../../i18n/country"; import * as tooltip from "../../ui/elements/Tooltip"; import * as moment from "moment"; import {format_number, network} from "../../ui/frames/chat"; +import {generateIconJQueryTag, getIconManager} from "tc-shared/file/Icons"; type InfoUpdateCallback = (info: ClientConnectionInfo) => any; @@ -311,8 +312,9 @@ function apply_groups(client: ClientEntry, tag: JQuery, modal: Modal, callbacks: if (!group) continue; //This shall never happen! container_empty.hide(); + container_entries.append($.spawn("div").addClass("entry").append( - client.channelTree.client.fileManager.icons.generateTag(group.properties.iconid), + generateIconJQueryTag(getIconManager().resolveIcon(group.properties.iconid, client.channelTree.client.getCurrentServerUniqueId(), client.channelTree.client.handlerId)), $.spawn("a").addClass("name").text(group.name + " (" + group.id + ")"), $.spawn("div").addClass("button-delete").append( $.spawn("div").addClass("icon_em client-delete").attr("title", tr("Delete group")).on('click', event => { diff --git a/shared/js/ui/modal/ModalConnect.ts b/shared/js/ui/modal/ModalConnect.ts index c596b006..c7573810 100644 --- a/shared/js/ui/modal/ModalConnect.ts +++ b/shared/js/ui/modal/ModalConnect.ts @@ -7,8 +7,9 @@ import {ConnectionProfile, defaultConnectProfile, findConnectProfile, availableC import {KeyCode} from "../../PPTListener"; import * as i18nc from "../../i18n/country"; import {spawnSettingsModal} from "../../ui/modal/ModalSettings"; -import {icon_cache_loader, IconManager} from "../../file/Icons"; +import {icon_cache_loader, IconManager} from "../../file/IconsOld"; import {server_connections} from "tc-shared/ConnectionManager"; +import {generateIconJQueryTag, getIconManager} from "tc-shared/file/Icons"; //FIXME: Move this shit out of this file! export namespace connection_log { @@ -290,6 +291,7 @@ export function spawnConnectModal(options: { /* connect history show */ { + for (const entry of connection_log.history().slice(0, 10)) { $.spawn("div").addClass("row").append( $.spawn("div").addClass("column delete").append($.spawn("div").addClass("icon_em client-delete")).on('click', event => { @@ -304,7 +306,7 @@ export function spawnConnectModal(options: { }) ).append( $.spawn("div").addClass("column name").append([ - IconManager.generate_tag(icon_cache_loader.load_icon(entry.icon_id, entry.server_unique_id)), + generateIconJQueryTag(getIconManager().resolveIcon(entry.icon_id, entry.server_unique_id), {animate: false}), $.spawn("a").text(entry.name) ]) ).append( diff --git a/shared/js/ui/modal/ModalCreateChannel.ts b/shared/js/ui/modal/ModalCreateChannel.ts index 45a2b8b7..e7ddfd1e 100644 --- a/shared/js/ui/modal/ModalCreateChannel.ts +++ b/shared/js/ui/modal/ModalCreateChannel.ts @@ -10,6 +10,7 @@ import * as tooltip from "../../ui/elements/Tooltip"; import {spawnIconSelect} from "../../ui/modal/ModalIconSelect"; import {hashPassword} from "../../utils/helpers"; import {sliderfy} from "../../ui/elements/Slider"; +import {generateIconJQueryTag, getIconManager} from "tc-shared/file/Icons"; export function createChannelModal(connection: ConnectionHandler, channel: ChannelEntry | undefined, parent: ChannelEntry | undefined, permissions: PermissionManager, callback: (properties?: ChannelProperties, permissions?: PermissionValue[]) => any) { let properties: ChannelProperties = { } as ChannelProperties; //The changes properties @@ -21,8 +22,9 @@ export function createChannelModal(connection: ConnectionHandler, channel: Chann channel_flag_maxfamilyclients_unlimited: true, channel_flag_maxclients_unlimited: true, }); - render_properties["channel_icon_tab"] = connection.fileManager.icons.generateTag(channel ? channel.properties.channel_icon_id : 0); - render_properties["channel_icon_general"] = connection.fileManager.icons.generateTag(channel ? channel.properties.channel_icon_id : 0); + + render_properties["channel_icon_tab"] = generateIconJQueryTag(getIconManager().resolveIcon(channel ? channel.properties.channel_icon_id : 0, connection.getCurrentServerUniqueId(), connection.handlerId)); + render_properties["channel_icon_general"] = generateIconJQueryTag(getIconManager().resolveIcon(channel ? channel.properties.channel_icon_id : 0, connection.getCurrentServerUniqueId(), connection.handlerId)); render_properties["create"] = !channel; let template = $("#tmpl_channel_edit").renderTag(render_properties); @@ -134,7 +136,7 @@ function applyGeneralListener(connection: ConnectionHandler, properties: Channel spawnIconSelect(connection, id => { const icon_node = tag.find(".icon-preview"); icon_node.children().remove(); - icon_node.append(connection.fileManager.icons.generateTag(id)); + icon_node.append(generateIconJQueryTag(getIconManager().resolveIcon(id, connection.getCurrentServerUniqueId(), connection.handlerId))); console.log("Selected icon ID: %d", id); properties.channel_icon_id = id; @@ -144,7 +146,7 @@ function applyGeneralListener(connection: ConnectionHandler, properties: Channel tag.find(".button-icon-remove").on('click', event => { const icon_node = tag.find(".icon-preview"); icon_node.children().remove(); - icon_node.append(connection.fileManager.icons.generateTag(0)); + icon_node.append(generateIconJQueryTag(getIconManager().resolveIcon(0, connection.getCurrentServerUniqueId(), connection.handlerId))); console.log("Remove channel icon"); properties.channel_icon_id = 0; diff --git a/shared/js/ui/modal/ModalGroupAssignment.ts b/shared/js/ui/modal/ModalGroupAssignment.ts index b50a4b40..aab85018 100644 --- a/shared/js/ui/modal/ModalGroupAssignment.ts +++ b/shared/js/ui/modal/ModalGroupAssignment.ts @@ -4,6 +4,7 @@ import * as log from "../../log"; import {ClientEntry} from "../../tree/Client"; import {GroupManager, GroupType} from "../../permission/GroupManager"; import PermissionType from "../../permission/PermissionType"; +import {generateIconJQueryTag, getIconManager} from "tc-shared/file/Icons"; let current_modal: Modal; export function createServerGroupAssignmentModal(client: ClientEntry, callback: (groups: number[], flag: boolean) => Promise) { @@ -27,7 +28,7 @@ export function createServerGroupAssignmentModal(client: ClientEntry, callback: entry["name"] = group.name; entry["disabled"] = !client.channelTree.client.permissions.neededPermission(PermissionType.I_GROUP_MEMBER_ADD_POWER).granted(group.requiredMemberRemovePower); entry["default"] = client.channelTree.server.properties.virtualserver_default_server_group == group.id; - tag["icon_" + group.id] = client.channelTree.client.fileManager.icons.generateTag(group.properties.iconid); + tag["icon_" + group.id] = generateIconJQueryTag(getIconManager().resolveIcon(group.properties.iconid, client.channelTree.server.properties.virtualserver_unique_identifier, client.channelTree.client.handlerId)); groups.push(entry); } diff --git a/shared/js/ui/modal/ModalIconSelect.ts b/shared/js/ui/modal/ModalIconSelect.ts index e01b506a..fe96099c 100644 --- a/shared/js/ui/modal/ModalIconSelect.ts +++ b/shared/js/ui/modal/ModalIconSelect.ts @@ -10,6 +10,7 @@ import * as crc32 from "../../crypto/crc32"; import {FileInfo} from "../../file/FileManager"; import {FileTransferState, TransferProvider} from "../../file/Transfer"; import {ErrorCode} from "../../connection/ErrorCode"; +import {generateIconJQueryTag, getIconManager} from "tc-shared/file/Icons"; export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id: number) => any, selected_icon?: number) { selected_icon = selected_icon || 0; @@ -49,22 +50,24 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id: const update_local_icons = (icons: number[]) => { container_icons_local.empty(); - for (const icon_id of icons) { - const tag = client.fileManager.icons.generateTag(icon_id, {animate: false}).attr('title', "Icon " + icon_id); + for (const iconId of icons) { + const iconTag = generateIconJQueryTag(getIconManager().resolveIcon(iconId, client.channelTree.server.properties.virtualserver_unique_identifier), { animate: false }); + + const tag = iconTag.attr('title', "Icon " + iconId); if (callback_icon) { tag.on('click', event => { container_icons.find(".selected").removeClass("selected"); tag.addClass("selected"); selected_container.empty().append(tag.clone()); - selected_icon = icon_id; + selected_icon = iconId; button_select.prop("disabled", false); }); tag.on('dblclick', event => { - callback_icon(icon_id); + callback_icon(iconId); modal.close(); }); - if (icon_id == selected_icon) + if (iconId == selected_icon) tag.trigger('click'); } tag.appendTo(container_icons_local); @@ -101,19 +104,21 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id: if (!chunk) return; for (const icon of chunk) { - const icon_id = parseInt(icon.name.substr("icon_".length)); - if (Number.isNaN(icon_id)) { + const iconId = parseInt(icon.name.substr("icon_".length)); + if (Number.isNaN(iconId)) { log.warn(LogCategory.GENERAL, tr("Received an unparsable icon within icon list (%o)"), icon); continue; } - const tag = client.fileManager.icons.generateTag(icon_id, {animate: false}).attr('title', "Icon " + icon_id); + + const iconTag = generateIconJQueryTag(getIconManager().resolveIcon(iconId, client.channelTree.server.properties.virtualserver_unique_identifier), { animate: false }); + const tag = iconTag.attr('title', "Icon " + iconId); if (callback_icon || allow_manage) { tag.on('click', event => { container_icons.find(".selected").removeClass("selected"); tag.addClass("selected"); selected_container.empty().append(tag.clone()); - selected_icon = icon_id; + selected_icon = iconId; button_select.prop("disabled", false); button_delete.prop("disabled", !allow_manage); }); @@ -121,10 +126,10 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id: if (!callback_icon) return; - callback_icon(icon_id); + callback_icon(iconId); modal.close(); }); - if (icon_id == selected_icon) + if (iconId == selected_icon) tag.trigger('click'); } tag.appendTo(container_icons_remote); @@ -158,7 +163,7 @@ export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id: if (selected_icon < 1000) return; /* we cant delete local icons */ - client.fileManager.icons.delete_icon(selected_icon).then(() => { + client.fileManager.deleteIcon(selected_icon).then(() => { selected.detach(); }).catch(error => { if (error instanceof CommandResult && error.id == ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS) diff --git a/shared/js/ui/modal/ModalServerEdit.ts b/shared/js/ui/modal/ModalServerEdit.ts index 2dc5c0e6..8ab00c45 100644 --- a/shared/js/ui/modal/ModalServerEdit.ts +++ b/shared/js/ui/modal/ModalServerEdit.ts @@ -6,6 +6,7 @@ import {hashPassword} from "../../utils/helpers"; import * as tooltip from "../../ui/elements/Tooltip"; import {spawnIconSelect} from "../../ui/modal/ModalIconSelect"; import {network} from "../../ui/frames/chat"; +import {generateIconJQueryTag, getIconManager} from "tc-shared/file/Icons"; export function createServerModal(server: ServerEntry, callback: (properties?: ServerProperties) => Promise) { const properties = Object.assign({}, server.properties); @@ -43,7 +44,7 @@ export function createServerModal(server: ServerEntry, callback: (properties?: S header: tr("Manage the Virtual Server"), body: () => { const template = $("#tmpl_server_edit").renderTag(Object.assign(Object.assign({}, server.properties), { - server_icon: server.channelTree.client.fileManager.icons.generateTag(server.properties.virtualserver_icon_id) + server_icon: generateIconJQueryTag(getIconManager().resolveIcon(server.properties.virtualserver_icon_id, server.properties.virtualserver_unique_identifier, server.channelTree.client.handlerId)) })); /* the tab functionality */ @@ -120,7 +121,7 @@ function apply_general_listener(tag: JQuery, server: ServerEntry, properties: Se spawnIconSelect(server.channelTree.client, id => { const icon_node = tag.find(".icon-preview"); icon_node.children().remove(); - icon_node.append(server.channelTree.client.fileManager.icons.generateTag(id)); + icon_node.append(generateIconJQueryTag(getIconManager().resolveIcon(id, server.properties.virtualserver_unique_identifier, server.channelTree.client.handlerId))); console.log("Selected icon ID: %d", id); properties.virtualserver_icon_id = id; @@ -131,7 +132,7 @@ function apply_general_listener(tag: JQuery, server: ServerEntry, properties: Se tag.find(".button-icon-remove").on('click', event => { const icon_node = tag.find(".icon-preview"); icon_node.children().remove(); - icon_node.append(server.channelTree.client.fileManager.icons.generateTag(0)); + icon_node.append(generateIconJQueryTag(getIconManager().resolveIcon(0, server.properties.virtualserver_unique_identifier))); console.log("Remove server icon"); properties.virtualserver_icon_id = 0; diff --git a/shared/js/ui/modal/permission/PermissionEditor.tsx b/shared/js/ui/modal/permission/PermissionEditor.tsx index 5436f6f8..701a3df7 100644 --- a/shared/js/ui/modal/permission/PermissionEditor.tsx +++ b/shared/js/ui/modal/permission/PermissionEditor.tsx @@ -11,11 +11,12 @@ import {LogCategory} from "tc-shared/log"; import ResizeObserver from "resize-observer-polyfill"; import {LoadingDots} from "tc-shared/ui/react-elements/LoadingDots"; import {Button} from "tc-shared/ui/react-elements/Button"; -import {IconRenderer, LocalIconRenderer} from "tc-shared/ui/react-elements/Icon"; +import {IconRenderer, LocalIconRenderer, RemoteIconRenderer} from "tc-shared/ui/react-elements/Icon"; import {ConnectionHandler} from "tc-shared/ConnectionHandler"; import * as contextmenu from "tc-shared/ui/elements/ContextMenu"; import {copy_to_clipboard} from "tc-shared/utils/helpers"; import {createInfoModal} from "tc-shared/ui/elements/Modal"; +import {getIconManager} from "tc-shared/file/Icons"; const cssStyle = require("./PermissionEditor.scss"); @@ -165,8 +166,9 @@ const ButtonIconPreview = (props: { events: Registry, co }); let icon; - if (!unset && iconId > 0) - icon = ; + if (!unset && iconId > 0) { + icon = ; + } return (
diff --git a/shared/js/ui/modal/permission/TabHandler.tsx b/shared/js/ui/modal/permission/TabHandler.tsx index 28b06861..23fe95f5 100644 --- a/shared/js/ui/modal/permission/TabHandler.tsx +++ b/shared/js/ui/modal/permission/TabHandler.tsx @@ -4,7 +4,7 @@ import {EventHandler, ReactEventHandler, Registry} from "tc-shared/events"; import {ChannelInfo, GroupProperties, PermissionModalEvents} from "tc-shared/ui/modal/permission/ModalPermissionEditor"; import {PermissionEditorEvents} from "tc-shared/ui/modal/permission/PermissionEditor"; import {ConnectionHandler} from "tc-shared/ConnectionHandler"; -import {LocalIconRenderer} from "tc-shared/ui/react-elements/Icon"; +import {LocalIconRenderer, RemoteIconRenderer} from "tc-shared/ui/react-elements/Icon"; import {createInputModal} from "tc-shared/ui/elements/Modal"; import {Translatable} from "tc-shared/ui/react-elements/i18n"; import {LoadingDots} from "tc-shared/ui/react-elements/LoadingDots"; @@ -14,6 +14,7 @@ import {copy_to_clipboard} from "tc-shared/utils/helpers"; import {FlatInputField} from "tc-shared/ui/react-elements/InputField"; import {arrayBufferBase64} from "tc-shared/utils/buffers"; import {tra} from "tc-shared/i18n/localize"; +import {getIconManager} from "tc-shared/file/Icons"; const cssStyle = require("./TabHandler.scss"); @@ -56,7 +57,7 @@ const GroupsListEntry = (props: { connection: ConnectionHandler, group: GroupPro return (
- +
{groupTypePrefix + props.group.name + " (" + props.group.id + ")"}
) @@ -476,8 +477,9 @@ class ServerClientList extends React.Component<{ connection: ConnectionHandler, onContextMenu={e => this.onListContextMenu(e)}> {selectedGroup ?
-
+
+ +
{groupTypePrefix + selectedGroup.name + " (" + selectedGroup.id + ")"}
@@ -847,7 +849,7 @@ class ChannelList extends React.Component<{ connection: ConnectionHandler, event id: e.id })} > - + {e.name + " (" + e.id + ")"}
))} diff --git a/shared/js/ui/react-elements/Icon.tsx b/shared/js/ui/react-elements/Icon.tsx index 113670a3..799e4508 100644 --- a/shared/js/ui/react-elements/Icon.tsx +++ b/shared/js/ui/react-elements/Icon.tsx @@ -1,8 +1,9 @@ import * as React from "react"; -import {LocalIcon} from "tc-shared/file/Icons"; +import {RemoteIcon} from "tc-shared/file/Icons"; +import {useState} from "react"; export const IconRenderer = (props: { - icon: string | LocalIcon; + icon: string; title?: string; className?: string; }) => { @@ -10,59 +11,42 @@ export const IconRenderer = (props: { return
; } else if(typeof props.icon === "string") { return
; - } else if(props.icon instanceof LocalIcon) { - return ; } else { throw "JQuery icons are not longer supported"; } } -export interface LoadedIconRenderer { - icon: LocalIcon; - title?: string; - className?: string; -} +export const RemoteIconRenderer = (props: { icon: RemoteIcon, className?: string, title?: string }) => { + const [ revision, setRevision ] = useState(0); -export class LocalIconRenderer extends React.Component { - private readonly callback_state_update; + props.icon.events.reactUse("notify_state_changed", () => setRevision(revision + 1)); - constructor(props) { - super(props); + switch (props.icon.getState()) { + case "empty": + case "destroyed": + return
; - this.callback_state_update = () => { - const icon = this.props.icon; - if(icon.status !== "destroyed") - this.forceUpdate(); - }; - } + case "loaded": + if(props.icon.iconId >= 0 && props.icon.iconId <= 1000) { + if(props.icon.iconId === 0) { + return
; + } - render() { - const icon = this.props.icon; - if(!icon || icon.status === "empty" || icon.status === "destroyed") - return
; - else if(icon.status === "loaded") { - if(icon.icon_id >= 0 && icon.icon_id <= 1000) { - if(icon.icon_id === 0) - return
; - return
; + return
; } - return
{this.props.title
; - } else if(icon.status === "loading") - return
; - else if(icon.status === "error") - return
; - } + return ( +
+ {props.title +
+ ); - componentDidMount(): void { - this.props.icon?.status_change_callbacks.push(this.callback_state_update); - } + case "loading": + return
; - componentWillUnmount(): void { - this.props.icon?.status_change_callbacks.remove(this.callback_state_update); - } + case "error": + return
; - componentDidUpdate(prevProps: Readonly, prevState: Readonly<{}>, snapshot?: any): void { - prevProps.icon?.status_change_callbacks.remove(this.callback_state_update); - this.props.icon?.status_change_callbacks.push(this.callback_state_update); + default: + throw "invalid icon state"; } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/shared/js/ui/tree/Channel.tsx b/shared/js/ui/tree/Channel.tsx index e728eac5..4d9e118c 100644 --- a/shared/js/ui/tree/Channel.tsx +++ b/shared/js/ui/tree/Channel.tsx @@ -5,7 +5,7 @@ import { } from "tc-shared/ui/react-elements/ReactComponentBase"; import * as React from "react"; import {ChannelEntry as ChannelEntryController, ChannelEvents, ChannelProperties} from "../../tree/Channel"; -import {LocalIconRenderer} from "tc-shared/ui/react-elements/Icon"; +import {RemoteIconRenderer} from "tc-shared/ui/react-elements/Icon"; import {EventHandler, ReactEventHandler} from "tc-shared/events"; import {Settings, settings} from "tc-shared/settings"; import {TreeEntry, UnreadMarker} from "tc-shared/ui/tree/TreeEntry"; @@ -14,6 +14,7 @@ import {ClientIconRenderer} from "tc-shared/ui/react-elements/Icons"; import {ClientIcon} from "svg-sprites/client-icons"; import {VoiceConnectionStatus} from "tc-shared/connection/VoiceConnection"; import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase"; +import {getIconManager} from "tc-shared/file/Icons"; const channelStyle = require("./Channel.scss"); const viewStyle = require("./View.scss"); @@ -84,25 +85,33 @@ class ChannelEntryIcons extends ReactComponentBase); + } - if (this.state.is_password_protected) + if (this.state.is_password_protected) { icons.push(); + } - if (this.state.is_music_quality) + if (this.state.is_music_quality) { icons.push(); + } - if (this.state.is_moderated) + if (this.state.is_moderated) { icons.push(); + } - if (this.state.custom_icon_id) - icons.push(); + if (this.state.custom_icon_id) { + const connection = this.props.channel.channelTree.client; + + icons.push(); + } if (!this.state.is_codec_supported) { icons.push(
@@ -112,9 +121,11 @@ class ChannelEntryIcons extends ReactComponentBase); } - return - {icons} - + return ( + + {icons} + + ); } @EventHandler("notify_properties_updated") diff --git a/shared/js/ui/tree/Client.tsx b/shared/js/ui/tree/Client.tsx index 56bf928a..0d7b129d 100644 --- a/shared/js/ui/tree/Client.tsx +++ b/shared/js/ui/tree/Client.tsx @@ -7,8 +7,6 @@ import * as React from "react"; import { ClientEntry as ClientEntryController, ClientEvents, - ClientProperties, - ClientType, LocalClientEntry, MusicClientEntry } from "../../tree/Client"; @@ -16,11 +14,12 @@ import {EventHandler, ReactEventHandler} from "tc-shared/events"; import {Group, GroupEvents} from "tc-shared/permission/GroupManager"; import {Settings, settings} from "tc-shared/settings"; import {TreeEntry, UnreadMarker} from "tc-shared/ui/tree/TreeEntry"; -import {LocalIconRenderer} from "tc-shared/ui/react-elements/Icon"; +import {RemoteIconRenderer} from "tc-shared/ui/react-elements/Icon"; import * as DOMPurify from "dompurify"; import {ClientIcon} from "svg-sprites/client-icons"; import {ClientIconRenderer} from "tc-shared/ui/react-elements/Icons"; import {useState} from "react"; +import {getIconManager} from "tc-shared/file/Icons"; const clientStyle = require("./Client.scss"); const viewStyle = require("./View.scss"); @@ -73,10 +72,13 @@ class ClientServerGroupIcons extends ReactComponentBase e?.properties.iconid) .sort((a, b) => a.properties.sortid - b.properties.sortid); if (group_icons.length === 0) return null; + + + const connection = this.props.client.channelTree.client; return [ group_icons.map(e => { - return ; + return }) ]; } @@ -126,14 +128,16 @@ class ClientChannelGroupIcon extends ReactComponentBase; + + const connection = this.props.client.channelTree.client; + return ; } @EventHandler("notify_properties_updated") private handlePropertiesUpdated(event: ClientEvents["notify_properties_updated"]) { - if (typeof event.updated_properties.client_servergroups) + if (typeof event.updated_properties.client_servergroups) { this.forceUpdate(); + } } } @@ -153,9 +157,11 @@ class ClientIcons extends ReactComponentBase { icons.push(); icons.push(); - if (this.props.client.properties.client_icon_id !== 0) - icons.push(); + if (this.props.client.properties.client_icon_id !== 0) { + const connection = this.props.client.channelTree.client; + icons.push(); + } return (
diff --git a/shared/js/ui/tree/Server.tsx b/shared/js/ui/tree/Server.tsx index 67904a10..003fcbda 100644 --- a/shared/js/ui/tree/Server.tsx +++ b/shared/js/ui/tree/Server.tsx @@ -1,11 +1,12 @@ import {BatchUpdateAssignment, BatchUpdateType} from "tc-shared/ui/react-elements/ReactComponentBase"; import {ServerEntry as ServerEntryController, ServerEvents} from "../../tree/Server"; import * as React from "react"; -import {LocalIconRenderer} from "tc-shared/ui/react-elements/Icon"; +import {LocalIconRenderer, RemoteIconRenderer} from "tc-shared/ui/react-elements/Icon"; import {EventHandler, ReactEventHandler} from "tc-shared/events"; import {Settings, settings} from "tc-shared/settings"; import {TreeEntry, UnreadMarker} from "tc-shared/ui/tree/TreeEntry"; import {ConnectionEvents, ConnectionState} from "tc-shared/ConnectionHandler"; +import {getIconManager} from "tc-shared/file/Icons"; const serverStyle = require("./Server.scss"); const viewStyle = require("./View.scss"); @@ -72,6 +73,8 @@ export class ServerEntry extends TreeEntry
{name}
- +
} diff --git a/shared/js/ui/tree/TreeEntry.tsx b/shared/js/ui/tree/TreeEntry.tsx index 0e1e652f..25d32f2a 100644 --- a/shared/js/ui/tree/TreeEntry.tsx +++ b/shared/js/ui/tree/TreeEntry.tsx @@ -23,5 +23,4 @@ export class UnreadMarker extends ReactComponentBase } } -export class TreeEntry extends ReactComponentBase { -} \ No newline at end of file +export class TreeEntry extends ReactComponentBase { } \ No newline at end of file diff --git a/shared/js/ui/tree/View.tsx b/shared/js/ui/tree/View.tsx index f80d7780..d27b4688 100644 --- a/shared/js/ui/tree/View.tsx +++ b/shared/js/ui/tree/View.tsx @@ -23,7 +23,6 @@ import {ConnectionEvents} from "tc-shared/ConnectionHandler"; const viewStyle = require("./View.scss"); - export interface ChannelTreeViewProperties { tree: ChannelTree; onMoveStart: (start: { x: number, y: number }, current: { x: number, y: number }) => void;