Removed the notify visibility event which hasn't been used any more

master
WolverinDEV 2021-04-05 20:06:44 +02:00
parent 1dfa10b09b
commit ae39685a40
15 changed files with 148 additions and 114 deletions

View File

@ -8,7 +8,6 @@ import {LogCategory, logError, logInfo, logTrace, logWarn} from "./log";
import {createErrorModal, createInputModal, Modal} from "./ui/elements/Modal";
import {hashPassword} from "./utils/helpers";
import {HandshakeHandler} from "./connection/HandshakeHandler";
import * as htmltags from "./ui/htmltags";
import {FilterMode, InputStartError, InputState} from "./voice/RecorderBase";
import {defaultRecorder, RecorderProfile} from "./voice/RecorderProfile";
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 {getDNSProvider} from "tc-shared/dns";
import {W2GPluginCmdHandler} from "tc-shared/ui/modal/video-viewer/W2GPlugin";
import * as htmltags from "./ui/htmltags";
assertMainApplication();
@ -1249,11 +1249,6 @@ export interface ConnectionEvents {
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 */
notify_handler_initialized: {}
}

View File

@ -102,8 +102,6 @@ export class ConnectionManager {
oldHandlerId: oldHandler?.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) {

View File

@ -19,6 +19,7 @@ import {AppUiEvents} from "tc-shared/ui/AppDefinitions";
import {ChannelTreeRenderer} from "tc-shared/ui/tree/Renderer";
import {ChannelTreeUIEvents} from "tc-shared/ui/tree/Definitions";
import {ImagePreviewHook} from "tc-shared/ui/frames/ImagePreview";
import {InternalModalHook} from "tc-shared/ui/react-elements/modal/internal";
const cssStyle = require("./AppRenderer.scss");
const VideoFrame = React.memo((props: { events: Registry<AppUiEvents> }) => {
@ -105,6 +106,10 @@ export const TeaAppMainView = (props: {
<ErrorBoundary>
<ImagePreviewHook />
</ErrorBoundary>
<ErrorBoundary>
<InternalModalHook />
</ErrorBoundary>
</div>
);
}

View File

@ -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>) {
let historyState: ChatHistoryState;
const localHistoryState = this.conversationManager.historyUiStates[conversation.getChatId()];

View File

@ -139,7 +139,6 @@ export interface AbstractConversationUiEvents {
}
notify_selected_chat: { chatId: "unselected" | string },
notify_panel_show: {},
notify_chat_event: {
chatId: string,
triggerUnread: boolean,

View File

@ -824,11 +824,6 @@ class ConversationMessages extends React.PureComponent<ConversationMessagesPrope
}
}
@EventHandler<AbstractConversationUiEvents>("notify_panel_show")
private handlePanelShow() {
this.fixScroll();
}
@EventHandler<AbstractConversationUiEvents>("query_conversation_history")
private handleQueryConversationHistory(event: AbstractConversationUiEvents["query_conversation_history"]) {
if (event.chatId !== this.currentChatId)

View File

@ -57,7 +57,6 @@ export class ChannelConversationController extends AbstractConversationControlle
this.connection = connection;
if(connection) {
this.initializeConnectionListener(connection);
/* FIXME: Update cross channel talk state! */
this.setConversationManager(connection.getChannelConversations());
} 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")
private handleMessageDelete(event: AbstractConversationUiEvents["action_delete_message"]) {
const conversation = this.conversationManager?.findConversationById(event.chatId);

View File

@ -73,7 +73,6 @@ export class PrivateConversationController extends AbstractConversationControlle
this.connection = connection;
if(connection) {
this.initializeConnectionListener(connection);
this.setConversationManager(connection.getPrivateConversations());
} else {
this.setConversationManager(undefined);
@ -81,15 +80,6 @@ export class PrivateConversationController extends AbstractConversationControlle
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) {
super.registerConversationManagerEvents(manager);

View File

@ -13,6 +13,7 @@ import {findRegisteredModal, RegisteredModal} from "tc-shared/ui/react-elements/
import {assertMainApplication} from "tc-shared/ui/utils";
import {InternalModalInstance} from "./internal";
import {ExternalModalController} from "./external/Controller";
import {LogCategory, logError} from "tc-shared/log";
assertMainApplication();
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_popout", () => {

View File

@ -116,7 +116,9 @@ export class ModalBodyRenderer extends React.PureComponent<{
this.props.className,
cssStyle["color-" + this.props.modalInstance.color()]
)}>
<ErrorBoundary>
{this.props.modalInstance.renderBody()}
</ErrorBoundary>
</div>
)
}
@ -139,8 +141,8 @@ export class ModalFrameRenderer extends React.PureComponent<{
export class PageModalRenderer extends React.PureComponent<{
modalInstance: AbstractModal,
onBackdropClicked: () => void,
children: React.ReactElement<ModalFrameRenderer>
}, {
children: React.ReactElement<ModalFrameRenderer>,
shown: boolean
}> {
constructor(props) {
@ -157,7 +159,7 @@ export class PageModalRenderer extends React.PureComponent<{
className={joinClassList(
cssStyle.modalPageContainer,
cssStyle["align-" + this.props.modalInstance.verticalAlignment()],
this.state.shown ? cssStyle.shown : undefined
this.props.shown ? cssStyle.shown : undefined
)}
tabIndex={-1}
role={"dialog"}

View File

@ -1,11 +1,12 @@
import {
AbstractModal,
constructAbstractModalClass, ModalInstanceController, ModalInstanceEvents,
constructAbstractModalClass,
ModalInstanceController,
ModalInstanceEvents,
ModalOptions,
ModalState
} from "tc-shared/ui/react-elements/modal/Definitions";
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
ModalBodyRenderer,
ModalFrameRenderer,
@ -15,36 +16,79 @@ import {
import {RegisteredModal} from "tc-shared/ui/react-elements/modal/Registry";
import {LogCategory, logError} from "tc-shared/log";
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 {
readonly instanceUniqueId: string;
readonly events: Registry<ModalInstanceEvents>;
readonly refRendererInstance: React.RefObject<InternalRendererInstance>;
private readonly modalKlass: RegisteredModal<any>;
private readonly constructorArguments: any[];
private readonly rendererInstance: React.RefObject<PageModalRenderer>;
private readonly modalOptions: ModalOptions;
private state: ModalState;
private modalInstance: AbstractModal;
private htmlContainer: HTMLDivElement;
public modalInstance: AbstractModal;
private modalInitializePromise: Promise<void>;
constructor(modalType: RegisteredModal<any>, constructorArguments: any[], modalOptions: ModalOptions) {
this.instanceUniqueId = guid();
this.events = new Registry<ModalInstanceEvents>();
this.modalKlass = modalType;
this.modalOptions = modalOptions;
this.constructorArguments = constructorArguments;
this.rendererInstance = React.createRef();
this.refRendererInstance = React.createRef();
this.state = ModalState.DESTROYED;
}
private async constructModal() {
if(this.htmlContainer || this.modalInstance) {
if(this.modalInstance) {
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["onInitialize"]();
} catch (error) {
this.destructModalInstance();
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");
}
this.htmlContainer = document.createElement("div");
document.body.appendChild(this.htmlContainer);
if(!internalModalContainer.current) {
this.destructModalInstance();
throw tr("missing modal hanging container");
}
await new Promise(resolve => {
ReactDOM.render(
<PageModalRenderer modalInstance={this.modalInstance} onBackdropClicked={this.getCloseCallback()} ref={this.rendererInstance}>
<ModalFrameRenderer windowed={false}>
<ModalFrameTopRenderer
replacePageTitle={false}
modalInstance={this.modalInstance}
onClose={this.getCloseCallback()}
onPopout={this.getPopoutCallback()}
onMinimize={this.getMinimizeCallback()}
/>
<ModalBodyRenderer modalInstance={this.modalInstance} />
</ModalFrameRenderer>
</PageModalRenderer>,
this.htmlContainer,
resolve
);
});
await new Promise(resolve => internalModalContainer.current.addModalInstance(this, resolve));
if(!this.refRendererInstance.current) {
this.destructModalInstance();
throw tr("missing rendered modal reference");
}
}
private destructModal() {
this.state = ModalState.DESTROYED;
if(this.htmlContainer) {
ReactDOM.unmountComponentAtNode(this.htmlContainer);
this.htmlContainer.remove();
this.htmlContainer = undefined;
this.destructModalInstance();
this.events.fire("notify_destroy");
}
if(this.modalInstance) {
this.modalInstance["onDestroy"]();
this.modalInstance = undefined;
private destructModalInstance() {
internalModalContainer.current?.removeModalInstance(this);
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 {
@ -118,13 +156,13 @@ export class InternalModalInstance implements ModalInstanceController {
await this.modalInitializePromise;
}
if(!this.rendererInstance.current) {
if(!this.refRendererInstance.current) {
return;
}
this.state = ModalState.SHOWN;
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");
}
@ -133,13 +171,13 @@ export class InternalModalInstance implements ModalInstanceController {
await this.modalInitializePromise;
}
if(!this.rendererInstance.current) {
if(!this.refRendererInstance.current) {
return;
}
this.state = ModalState.HIDDEN;
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? */
await new Promise(resolve => setTimeout(resolve, 500));
@ -154,11 +192,11 @@ export class InternalModalInstance implements ModalInstanceController {
this.events.destroy();
}
protected getCloseCallback() {
public getCloseCallback() {
return () => this.events.fire("action_close");
}
protected getPopoutCallback() {
public getPopoutCallback() {
if(!this.modalKlass.popoutSupported) {
return undefined;
}
@ -170,8 +208,48 @@ export class InternalModalInstance implements ModalInstanceController {
return () => this.events.fire("action_popout");
}
protected getMinimizeCallback() {
public getMinimizeCallback() {
/* We can't minimize any windows */
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} />
));

View File

@ -680,8 +680,6 @@ export function initializeChannelTreeController(events: Registry<ChannelTreeUIEv
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_selected_entry", () => controller.sendSelectedEntry());
events.on("query_channel_info", event => {

View File

@ -103,7 +103,6 @@ export interface ChannelTreeUIEvents {
notify_unread_state: { treeEntryId: number, unread: boolean },
notify_visibility_changed: { visible: boolean },
notify_destroy: {}
}

View File

@ -110,25 +110,6 @@ export class ChannelTreeView extends ReactComponentBase<ChannelTreeViewPropertie
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() {
const entryHeight = ChannelTreeView.EntryHeightEm * this.state.fontSize;
let viewEntryCount = Math.ceil(this.state.viewHeight / entryHeight);

File diff suppressed because one or more lines are too long