Removed the notify visibility event which hasn't been used any more
This commit is contained in:
parent
1dfa10b09b
commit
ae39685a40
15 changed files with 148 additions and 114 deletions
|
@ -8,7 +8,6 @@ import {LogCategory, logError, logInfo, logTrace, logWarn} from "./log";
|
||||||
import {createErrorModal, createInputModal, Modal} from "./ui/elements/Modal";
|
import {createErrorModal, createInputModal, Modal} from "./ui/elements/Modal";
|
||||||
import {hashPassword} from "./utils/helpers";
|
import {hashPassword} from "./utils/helpers";
|
||||||
import {HandshakeHandler} from "./connection/HandshakeHandler";
|
import {HandshakeHandler} from "./connection/HandshakeHandler";
|
||||||
import * as htmltags from "./ui/htmltags";
|
|
||||||
import {FilterMode, InputStartError, InputState} from "./voice/RecorderBase";
|
import {FilterMode, InputStartError, InputState} from "./voice/RecorderBase";
|
||||||
import {defaultRecorder, RecorderProfile} from "./voice/RecorderProfile";
|
import {defaultRecorder, RecorderProfile} from "./voice/RecorderProfile";
|
||||||
import {Regex} from "./ui/modal/ModalConnect";
|
import {Regex} from "./ui/modal/ModalConnect";
|
||||||
|
@ -38,6 +37,7 @@ import {ConnectParameters} from "tc-shared/ui/modal/connect/Controller";
|
||||||
import {assertMainApplication} from "tc-shared/ui/utils";
|
import {assertMainApplication} from "tc-shared/ui/utils";
|
||||||
import {getDNSProvider} from "tc-shared/dns";
|
import {getDNSProvider} from "tc-shared/dns";
|
||||||
import {W2GPluginCmdHandler} from "tc-shared/ui/modal/video-viewer/W2GPlugin";
|
import {W2GPluginCmdHandler} from "tc-shared/ui/modal/video-viewer/W2GPlugin";
|
||||||
|
import * as htmltags from "./ui/htmltags";
|
||||||
|
|
||||||
assertMainApplication();
|
assertMainApplication();
|
||||||
|
|
||||||
|
@ -1249,11 +1249,6 @@ export interface ConnectionEvents {
|
||||||
newState: ConnectionState
|
newState: ConnectionState
|
||||||
},
|
},
|
||||||
|
|
||||||
/* the handler has become visible/invisible for the client */
|
|
||||||
notify_visibility_changed: {
|
|
||||||
visible: boolean
|
|
||||||
},
|
|
||||||
|
|
||||||
/* fill only trigger once, after everything has been constructed */
|
/* fill only trigger once, after everything has been constructed */
|
||||||
notify_handler_initialized: {}
|
notify_handler_initialized: {}
|
||||||
}
|
}
|
|
@ -102,8 +102,6 @@ export class ConnectionManager {
|
||||||
oldHandlerId: oldHandler?.handlerId,
|
oldHandlerId: oldHandler?.handlerId,
|
||||||
newHandlerId: handler?.handlerId
|
newHandlerId: handler?.handlerId
|
||||||
});
|
});
|
||||||
oldHandler?.events().fire("notify_visibility_changed", { visible: false });
|
|
||||||
handler?.events().fire("notify_visibility_changed", { visible: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
swapHandlerOrder(handlerA: ConnectionHandler, handlerB: ConnectionHandler) {
|
swapHandlerOrder(handlerA: ConnectionHandler, handlerB: ConnectionHandler) {
|
||||||
|
|
|
@ -19,6 +19,7 @@ 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";
|
import {ImagePreviewHook} from "tc-shared/ui/frames/ImagePreview";
|
||||||
|
import {InternalModalHook} from "tc-shared/ui/react-elements/modal/internal";
|
||||||
|
|
||||||
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> }) => {
|
||||||
|
@ -105,6 +106,10 @@ export const TeaAppMainView = (props: {
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<ImagePreviewHook />
|
<ImagePreviewHook />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
|
||||||
|
<ErrorBoundary>
|
||||||
|
<InternalModalHook />
|
||||||
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -110,11 +110,6 @@ export abstract class AbstractConversationController<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Is this even a thing? */
|
|
||||||
handlePanelShow() {
|
|
||||||
this.uiEvents.fire_react("notify_panel_show");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected reportStateToUI(conversation: AbstractChat<any>) {
|
protected reportStateToUI(conversation: AbstractChat<any>) {
|
||||||
let historyState: ChatHistoryState;
|
let historyState: ChatHistoryState;
|
||||||
const localHistoryState = this.conversationManager.historyUiStates[conversation.getChatId()];
|
const localHistoryState = this.conversationManager.historyUiStates[conversation.getChatId()];
|
||||||
|
|
|
@ -139,7 +139,6 @@ export interface AbstractConversationUiEvents {
|
||||||
}
|
}
|
||||||
|
|
||||||
notify_selected_chat: { chatId: "unselected" | string },
|
notify_selected_chat: { chatId: "unselected" | string },
|
||||||
notify_panel_show: {},
|
|
||||||
notify_chat_event: {
|
notify_chat_event: {
|
||||||
chatId: string,
|
chatId: string,
|
||||||
triggerUnread: boolean,
|
triggerUnread: boolean,
|
||||||
|
|
|
@ -824,11 +824,6 @@ class ConversationMessages extends React.PureComponent<ConversationMessagesPrope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler<AbstractConversationUiEvents>("notify_panel_show")
|
|
||||||
private handlePanelShow() {
|
|
||||||
this.fixScroll();
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler<AbstractConversationUiEvents>("query_conversation_history")
|
@EventHandler<AbstractConversationUiEvents>("query_conversation_history")
|
||||||
private handleQueryConversationHistory(event: AbstractConversationUiEvents["query_conversation_history"]) {
|
private handleQueryConversationHistory(event: AbstractConversationUiEvents["query_conversation_history"]) {
|
||||||
if (event.chatId !== this.currentChatId)
|
if (event.chatId !== this.currentChatId)
|
||||||
|
|
|
@ -57,7 +57,6 @@ export class ChannelConversationController extends AbstractConversationControlle
|
||||||
|
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
if(connection) {
|
if(connection) {
|
||||||
this.initializeConnectionListener(connection);
|
|
||||||
/* FIXME: Update cross channel talk state! */
|
/* FIXME: Update cross channel talk state! */
|
||||||
this.setConversationManager(connection.getChannelConversations());
|
this.setConversationManager(connection.getChannelConversations());
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,16 +64,6 @@ export class ChannelConversationController extends AbstractConversationControlle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeConnectionListener(connection: ConnectionHandler) {
|
|
||||||
this.connectionListener.push(connection.events().on("notify_visibility_changed", event => {
|
|
||||||
if(!event.visible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.handlePanelShow();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler<AbstractConversationUiEvents>("action_delete_message")
|
@EventHandler<AbstractConversationUiEvents>("action_delete_message")
|
||||||
private handleMessageDelete(event: AbstractConversationUiEvents["action_delete_message"]) {
|
private handleMessageDelete(event: AbstractConversationUiEvents["action_delete_message"]) {
|
||||||
const conversation = this.conversationManager?.findConversationById(event.chatId);
|
const conversation = this.conversationManager?.findConversationById(event.chatId);
|
||||||
|
|
|
@ -73,7 +73,6 @@ export class PrivateConversationController extends AbstractConversationControlle
|
||||||
|
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
if(connection) {
|
if(connection) {
|
||||||
this.initializeConnectionListener(connection);
|
|
||||||
this.setConversationManager(connection.getPrivateConversations());
|
this.setConversationManager(connection.getPrivateConversations());
|
||||||
} else {
|
} else {
|
||||||
this.setConversationManager(undefined);
|
this.setConversationManager(undefined);
|
||||||
|
@ -81,15 +80,6 @@ export class PrivateConversationController extends AbstractConversationControlle
|
||||||
this.reportConversationList();
|
this.reportConversationList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeConnectionListener(connection: ConnectionHandler) {
|
|
||||||
this.connectionListener.push(connection.events().on("notify_visibility_changed", event => {
|
|
||||||
if(!event.visible)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.handlePanelShow();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected registerConversationManagerEvents(manager: PrivateConversationManager) {
|
protected registerConversationManagerEvents(manager: PrivateConversationManager) {
|
||||||
super.registerConversationManagerEvents(manager);
|
super.registerConversationManagerEvents(manager);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {findRegisteredModal, RegisteredModal} from "tc-shared/ui/react-elements/
|
||||||
import {assertMainApplication} from "tc-shared/ui/utils";
|
import {assertMainApplication} from "tc-shared/ui/utils";
|
||||||
import {InternalModalInstance} from "./internal";
|
import {InternalModalInstance} from "./internal";
|
||||||
import {ExternalModalController} from "./external/Controller";
|
import {ExternalModalController} from "./external/Controller";
|
||||||
|
import {LogCategory, logError} from "tc-shared/log";
|
||||||
|
|
||||||
assertMainApplication();
|
assertMainApplication();
|
||||||
export class GenericModalController<T extends keyof ModalConstructorArguments> implements ModalController {
|
export class GenericModalController<T extends keyof ModalConstructorArguments> implements ModalController {
|
||||||
|
@ -82,7 +83,15 @@ export class GenericModalController<T extends keyof ModalConstructorArguments> i
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
events.on("action_close", () => this.destroy());
|
events.on("action_close", () => {
|
||||||
|
if(this.popedOut) {
|
||||||
|
this.destroy();
|
||||||
|
} else {
|
||||||
|
this.hide().catch(error => {
|
||||||
|
logError(LogCategory.GENERAL, tr("Failed to hide modal: %o"), error);
|
||||||
|
}).then(() => this.destroy());
|
||||||
|
}
|
||||||
|
});
|
||||||
events.on("action_minimize", () => this.instance.minimize());
|
events.on("action_minimize", () => this.instance.minimize());
|
||||||
|
|
||||||
events.on("action_popout", () => {
|
events.on("action_popout", () => {
|
||||||
|
|
|
@ -116,7 +116,9 @@ export class ModalBodyRenderer extends React.PureComponent<{
|
||||||
this.props.className,
|
this.props.className,
|
||||||
cssStyle["color-" + this.props.modalInstance.color()]
|
cssStyle["color-" + this.props.modalInstance.color()]
|
||||||
)}>
|
)}>
|
||||||
|
<ErrorBoundary>
|
||||||
{this.props.modalInstance.renderBody()}
|
{this.props.modalInstance.renderBody()}
|
||||||
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -139,8 +141,8 @@ export class ModalFrameRenderer extends React.PureComponent<{
|
||||||
export class PageModalRenderer extends React.PureComponent<{
|
export class PageModalRenderer extends React.PureComponent<{
|
||||||
modalInstance: AbstractModal,
|
modalInstance: AbstractModal,
|
||||||
onBackdropClicked: () => void,
|
onBackdropClicked: () => void,
|
||||||
children: React.ReactElement<ModalFrameRenderer>
|
children: React.ReactElement<ModalFrameRenderer>,
|
||||||
}, {
|
|
||||||
shown: boolean
|
shown: boolean
|
||||||
}> {
|
}> {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -157,7 +159,7 @@ export class PageModalRenderer extends React.PureComponent<{
|
||||||
className={joinClassList(
|
className={joinClassList(
|
||||||
cssStyle.modalPageContainer,
|
cssStyle.modalPageContainer,
|
||||||
cssStyle["align-" + this.props.modalInstance.verticalAlignment()],
|
cssStyle["align-" + this.props.modalInstance.verticalAlignment()],
|
||||||
this.state.shown ? cssStyle.shown : undefined
|
this.props.shown ? cssStyle.shown : undefined
|
||||||
)}
|
)}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
role={"dialog"}
|
role={"dialog"}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import {
|
import {
|
||||||
AbstractModal,
|
AbstractModal,
|
||||||
constructAbstractModalClass, ModalInstanceController, ModalInstanceEvents,
|
constructAbstractModalClass,
|
||||||
|
ModalInstanceController,
|
||||||
|
ModalInstanceEvents,
|
||||||
ModalOptions,
|
ModalOptions,
|
||||||
ModalState
|
ModalState
|
||||||
} from "tc-shared/ui/react-elements/modal/Definitions";
|
} from "tc-shared/ui/react-elements/modal/Definitions";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as ReactDOM from "react-dom";
|
|
||||||
import {
|
import {
|
||||||
ModalBodyRenderer,
|
ModalBodyRenderer,
|
||||||
ModalFrameRenderer,
|
ModalFrameRenderer,
|
||||||
|
@ -15,36 +16,79 @@ import {
|
||||||
import {RegisteredModal} from "tc-shared/ui/react-elements/modal/Registry";
|
import {RegisteredModal} from "tc-shared/ui/react-elements/modal/Registry";
|
||||||
import {LogCategory, logError} from "tc-shared/log";
|
import {LogCategory, logError} from "tc-shared/log";
|
||||||
import {Registry} from "tc-events";
|
import {Registry} from "tc-events";
|
||||||
|
import {guid} from "tc-shared/crypto/uid";
|
||||||
|
import {ErrorBoundary} from "tc-shared/ui/react-elements/ErrorBoundary";
|
||||||
|
|
||||||
|
class InternalRendererInstance extends React.PureComponent<{
|
||||||
|
instance: InternalModalInstance,
|
||||||
|
}, {
|
||||||
|
shown: boolean
|
||||||
|
}> {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
shown: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const instance = this.props.instance;
|
||||||
|
if(!instance?.modalInstance) {
|
||||||
|
throw tr("missing modal instance");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageModalRenderer modalInstance={instance.modalInstance} onBackdropClicked={instance.getCloseCallback()} shown={this.state.shown}>
|
||||||
|
<ModalFrameRenderer windowed={false}>
|
||||||
|
<ModalFrameTopRenderer
|
||||||
|
replacePageTitle={false}
|
||||||
|
modalInstance={instance.modalInstance}
|
||||||
|
|
||||||
|
onClose={instance.getCloseCallback()}
|
||||||
|
onPopout={instance.getPopoutCallback()}
|
||||||
|
onMinimize={instance.getMinimizeCallback()}
|
||||||
|
/>
|
||||||
|
<ModalBodyRenderer modalInstance={instance.modalInstance} />
|
||||||
|
</ModalFrameRenderer>
|
||||||
|
</PageModalRenderer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
/* TODO: May notify the instance about this if this wasn't planned */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class InternalModalInstance implements ModalInstanceController {
|
export class InternalModalInstance implements ModalInstanceController {
|
||||||
|
readonly instanceUniqueId: string;
|
||||||
readonly events: Registry<ModalInstanceEvents>;
|
readonly events: Registry<ModalInstanceEvents>;
|
||||||
|
readonly refRendererInstance: React.RefObject<InternalRendererInstance>;
|
||||||
|
|
||||||
private readonly modalKlass: RegisteredModal<any>;
|
private readonly modalKlass: RegisteredModal<any>;
|
||||||
private readonly constructorArguments: any[];
|
private readonly constructorArguments: any[];
|
||||||
private readonly rendererInstance: React.RefObject<PageModalRenderer>;
|
|
||||||
|
|
||||||
private readonly modalOptions: ModalOptions;
|
private readonly modalOptions: ModalOptions;
|
||||||
|
|
||||||
private state: ModalState;
|
private state: ModalState;
|
||||||
|
|
||||||
private modalInstance: AbstractModal;
|
public modalInstance: AbstractModal;
|
||||||
private htmlContainer: HTMLDivElement;
|
|
||||||
|
|
||||||
private modalInitializePromise: Promise<void>;
|
private modalInitializePromise: Promise<void>;
|
||||||
|
|
||||||
constructor(modalType: RegisteredModal<any>, constructorArguments: any[], modalOptions: ModalOptions) {
|
constructor(modalType: RegisteredModal<any>, constructorArguments: any[], modalOptions: ModalOptions) {
|
||||||
|
this.instanceUniqueId = guid();
|
||||||
this.events = new Registry<ModalInstanceEvents>();
|
this.events = new Registry<ModalInstanceEvents>();
|
||||||
|
|
||||||
this.modalKlass = modalType;
|
this.modalKlass = modalType;
|
||||||
this.modalOptions = modalOptions;
|
this.modalOptions = modalOptions;
|
||||||
this.constructorArguments = constructorArguments;
|
this.constructorArguments = constructorArguments;
|
||||||
|
|
||||||
this.rendererInstance = React.createRef();
|
this.refRendererInstance = React.createRef();
|
||||||
this.state = ModalState.DESTROYED;
|
this.state = ModalState.DESTROYED;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async constructModal() {
|
private async constructModal() {
|
||||||
if(this.htmlContainer || this.modalInstance) {
|
if(this.modalInstance) {
|
||||||
throw tr("internal modal has already been constructed");
|
throw tr("internal modal has already been constructed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,47 +101,41 @@ export class InternalModalInstance implements ModalInstanceController {
|
||||||
this.modalInstance = constructAbstractModalClass(modalClass.default, { windowed: false }, this.constructorArguments);
|
this.modalInstance = constructAbstractModalClass(modalClass.default, { windowed: false }, this.constructorArguments);
|
||||||
this.modalInstance["onInitialize"]();
|
this.modalInstance["onInitialize"]();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
this.destructModalInstance();
|
||||||
logError(LogCategory.GENERAL, tr("Failed to create new modal of instance type %s: %o"), this.modalKlass.modalId, error);
|
logError(LogCategory.GENERAL, tr("Failed to create new modal of instance type %s: %o"), this.modalKlass.modalId, error);
|
||||||
throw tr("failed to create new modal instance");
|
throw tr("failed to create new modal instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.htmlContainer = document.createElement("div");
|
if(!internalModalContainer.current) {
|
||||||
document.body.appendChild(this.htmlContainer);
|
this.destructModalInstance();
|
||||||
|
throw tr("missing modal hanging container");
|
||||||
|
}
|
||||||
|
|
||||||
await new Promise(resolve => {
|
await new Promise(resolve => internalModalContainer.current.addModalInstance(this, resolve));
|
||||||
ReactDOM.render(
|
if(!this.refRendererInstance.current) {
|
||||||
<PageModalRenderer modalInstance={this.modalInstance} onBackdropClicked={this.getCloseCallback()} ref={this.rendererInstance}>
|
this.destructModalInstance();
|
||||||
<ModalFrameRenderer windowed={false}>
|
throw tr("missing rendered modal reference");
|
||||||
<ModalFrameTopRenderer
|
}
|
||||||
replacePageTitle={false}
|
|
||||||
modalInstance={this.modalInstance}
|
|
||||||
|
|
||||||
onClose={this.getCloseCallback()}
|
|
||||||
onPopout={this.getPopoutCallback()}
|
|
||||||
onMinimize={this.getMinimizeCallback()}
|
|
||||||
/>
|
|
||||||
<ModalBodyRenderer modalInstance={this.modalInstance} />
|
|
||||||
</ModalFrameRenderer>
|
|
||||||
</PageModalRenderer>,
|
|
||||||
this.htmlContainer,
|
|
||||||
resolve
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private destructModal() {
|
private destructModal() {
|
||||||
this.state = ModalState.DESTROYED;
|
this.state = ModalState.DESTROYED;
|
||||||
if(this.htmlContainer) {
|
this.destructModalInstance();
|
||||||
ReactDOM.unmountComponentAtNode(this.htmlContainer);
|
this.events.fire("notify_destroy");
|
||||||
this.htmlContainer.remove();
|
|
||||||
this.htmlContainer = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.modalInstance) {
|
private destructModalInstance() {
|
||||||
this.modalInstance["onDestroy"]();
|
internalModalContainer.current?.removeModalInstance(this);
|
||||||
this.modalInstance = undefined;
|
if(!this.modalInstance) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
this.events.fire("notify_destroy");
|
|
||||||
|
try {
|
||||||
|
this.modalInstance["onDestroy"]();
|
||||||
|
} catch (error) {
|
||||||
|
logError(LogCategory.GENERAL, tr("Failed to invoke the destroy callback on the created modal instance: %o"), error);
|
||||||
|
}
|
||||||
|
this.modalInstance = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
getState(): ModalState {
|
getState(): ModalState {
|
||||||
|
@ -118,13 +156,13 @@ export class InternalModalInstance implements ModalInstanceController {
|
||||||
await this.modalInitializePromise;
|
await this.modalInitializePromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.rendererInstance.current) {
|
if(!this.refRendererInstance.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = ModalState.SHOWN;
|
|
||||||
this.modalInstance["onOpen"]();
|
this.modalInstance["onOpen"]();
|
||||||
await new Promise(resolve => this.rendererInstance.current.setState({ shown: true }, resolve));
|
this.state = ModalState.SHOWN;
|
||||||
|
await new Promise(resolve => this.refRendererInstance.current.setState({ shown: true }, resolve));
|
||||||
this.events.fire("notify_open");
|
this.events.fire("notify_open");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,13 +171,13 @@ export class InternalModalInstance implements ModalInstanceController {
|
||||||
await this.modalInitializePromise;
|
await this.modalInitializePromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.rendererInstance.current) {
|
if(!this.refRendererInstance.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = ModalState.HIDDEN;
|
this.state = ModalState.HIDDEN;
|
||||||
this.modalInstance["onClose"]();
|
this.modalInstance["onClose"]();
|
||||||
await new Promise(resolve => this.rendererInstance.current.setState({ shown: false }, resolve));
|
await new Promise(resolve => this.refRendererInstance.current.setState({ shown: false }, resolve));
|
||||||
|
|
||||||
/* TODO: Somehow get the real animation finish signal? */
|
/* TODO: Somehow get the real animation finish signal? */
|
||||||
await new Promise(resolve => setTimeout(resolve, 500));
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
|
@ -154,11 +192,11 @@ export class InternalModalInstance implements ModalInstanceController {
|
||||||
this.events.destroy();
|
this.events.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getCloseCallback() {
|
public getCloseCallback() {
|
||||||
return () => this.events.fire("action_close");
|
return () => this.events.fire("action_close");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getPopoutCallback() {
|
public getPopoutCallback() {
|
||||||
if(!this.modalKlass.popoutSupported) {
|
if(!this.modalKlass.popoutSupported) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -170,8 +208,48 @@ export class InternalModalInstance implements ModalInstanceController {
|
||||||
return () => this.events.fire("action_popout");
|
return () => this.events.fire("action_popout");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getMinimizeCallback() {
|
public getMinimizeCallback() {
|
||||||
/* We can't minimize any windows */
|
/* We can't minimize any windows */
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const internalModalContainer: React.RefObject<InternalModalHookInner> = React.createRef();
|
||||||
|
class InternalModalHookInner extends React.PureComponent<{}, {
|
||||||
|
revision: number
|
||||||
|
}> {
|
||||||
|
private modalStack: InternalModalInstance[];
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.modalStack = [];
|
||||||
|
this.state = { revision: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
this.modalStack.map(modal => (
|
||||||
|
<ErrorBoundary key={modal.instanceUniqueId}>
|
||||||
|
<InternalRendererInstance instance={modal} ref={modal.refRendererInstance} />
|
||||||
|
</ErrorBoundary>
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
addModalInstance(modal: InternalModalInstance, callbackRendered?: () => void) {
|
||||||
|
this.modalStack.push(modal);
|
||||||
|
this.setState({ revision: performance.now() }, callbackRendered);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeModalInstance(modal: InternalModalInstance) {
|
||||||
|
if(!this.modalStack.remove(modal)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({ revision: performance.now() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InternalModalHook = React.memo(() => (
|
||||||
|
<InternalModalHookInner ref={internalModalContainer} />
|
||||||
|
));
|
|
@ -680,8 +680,6 @@ export function initializeChannelTreeController(events: Registry<ChannelTreeUIEv
|
||||||
events.fire_react("notify_unread_state", { treeEntryId: event.treeEntryId, unread: entry.isUnread() });
|
events.fire_react("notify_unread_state", { treeEntryId: event.treeEntryId, unread: entry.isUnread() });
|
||||||
});
|
});
|
||||||
|
|
||||||
events.on("notify_destroy", channelTree.client.events().on("notify_visibility_changed", event => events.fire_react("notify_visibility_changed", event)));
|
|
||||||
|
|
||||||
events.on("query_tree_entries", event => controller.sendChannelTreeEntriesFull(event.fullInfo ? undefined : []));
|
events.on("query_tree_entries", event => controller.sendChannelTreeEntriesFull(event.fullInfo ? undefined : []));
|
||||||
events.on("query_selected_entry", () => controller.sendSelectedEntry());
|
events.on("query_selected_entry", () => controller.sendSelectedEntry());
|
||||||
events.on("query_channel_info", event => {
|
events.on("query_channel_info", event => {
|
||||||
|
|
|
@ -103,7 +103,6 @@ export interface ChannelTreeUIEvents {
|
||||||
|
|
||||||
notify_unread_state: { treeEntryId: number, unread: boolean },
|
notify_unread_state: { treeEntryId: number, unread: boolean },
|
||||||
|
|
||||||
notify_visibility_changed: { visible: boolean },
|
|
||||||
notify_destroy: {}
|
notify_destroy: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,25 +110,6 @@ export class ChannelTreeView extends ReactComponentBase<ChannelTreeViewPropertie
|
||||||
this.resizeObserver = undefined;
|
this.resizeObserver = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler<ChannelTreeUIEvents>("notify_visibility_changed")
|
|
||||||
private handleVisibilityChanged(event: ChannelTreeUIEvents["notify_visibility_changed"]) {
|
|
||||||
if (!event.visible) {
|
|
||||||
this.setState({smoothScroll: false});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.scrollFixRequested) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.scrollFixRequested = true;
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
this.scrollFixRequested = false;
|
|
||||||
this.refContainer.current.scrollTop = this.state.scrollOffset;
|
|
||||||
this.setState({smoothScroll: true});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private visibleEntries() {
|
private visibleEntries() {
|
||||||
const entryHeight = ChannelTreeView.EntryHeightEm * this.state.fontSize;
|
const entryHeight = ChannelTreeView.EntryHeightEm * this.state.fontSize;
|
||||||
let viewEntryCount = Math.ceil(this.state.viewHeight / entryHeight);
|
let viewEntryCount = Math.ceil(this.state.viewHeight / entryHeight);
|
||||||
|
|
5
shared/svg-sprites/client-icons.d.ts
vendored
5
shared/svg-sprites/client-icons.d.ts
vendored
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue