[FIX] Modal keeps state if reset too fast. (#23791)

* Remove subscription, queue updates

* use key instead of queue

* Fix types

* little adjustments
pull/23901/head
gabriellsh 4 years ago committed by GitHub
parent abc59e1b9d
commit 49fe4e2cca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 81
      client/lib/imperativeModal.ts
  2. 34
      client/views/hooks/useImperativeModal.ts

@ -1,81 +1,28 @@
import { Emitter } from '@rocket.chat/emitter';
import { ComponentType } from 'react';
import { Subscription, Unsubscribe } from 'use-subscription';
type BlazeModalOptions = {
confirmButtonText?: string;
cancelButtonText?: string;
showCancelButton?: boolean;
confirmButtonColor?: string;
cancelButtonColor?: string;
allowOutsideClick?: boolean;
confirmOnEnter?: boolean;
closeOnConfirm?: boolean;
closeOnEscape?: boolean;
type?: 'input';
inputType?: 'text' | 'password';
inputActionText?: string;
inputAction?: () => any;
inputPlaceholder?: string;
modalIcon?: string;
timer?: number;
dontAskAgain?: {
action: string;
label: string;
};
data?: Record<string, any>;
content?: string;
template?: string;
title?: string;
text?: string;
html?: boolean;
type ReactModalDescriptor<TProps extends {}> = {
component: ComponentType<TProps>;
props?: TProps;
};
type BlazeModalDescriptor = {
options: BlazeModalOptions;
confirmFn?: () => any;
cancelFn?: () => any;
};
type ReactModalDescriptor<Props extends {} = {}> = {
component: ComponentType<Props>;
props?: Props;
};
type ModalDescriptor = BlazeModalDescriptor | ReactModalDescriptor | null;
class ImperativeModalSubscription
extends Emitter<{ update: void }>
implements Subscription<ModalDescriptor>
{
private descriptor: ModalDescriptor = null;
getCurrentValue = (): ModalDescriptor => this.descriptor;
subscribe = (callback: () => void): Unsubscribe => this.on('update', callback);
type ModalDescriptor = ReactModalDescriptor<{}> | null;
setCurrentValue(descriptor: ModalDescriptor): void {
this.descriptor = descriptor;
this.emit('update');
class ImperativeModalEmmiter extends Emitter<{ update: ModalDescriptor }> {
update(descriptor: ModalDescriptor): void {
this.emit('update', descriptor);
}
open: {
(descriptor: BlazeModalDescriptor): void;
<Props = {}>(descriptor: ReactModalDescriptor<Props>): void;
} = (templateOrDescriptor: ModalDescriptor): void => {
this.setCurrentValue(templateOrDescriptor);
open = <TProps extends {}>(descriptor: ReactModalDescriptor<TProps> | null): void => {
// There are some TS shenanigans causing errors if this is not asserted
// Since this method is for internal use only, it's ok to use this here
// This will not affect prop types inference when using the method.
this.update(descriptor as ModalDescriptor);
};
close = (): void => {
this.setCurrentValue(null);
this.update(null);
};
}
export const imperativeModal = new ImperativeModalSubscription();
export const imperativeModal = new ImperativeModalEmmiter();

@ -1,26 +1,22 @@
import { createElement, useEffect, Dispatch, SetStateAction, ReactNode } from 'react';
import { useSubscription } from 'use-subscription';
import { imperativeModal } from '../../lib/imperativeModal';
export const useImperativeModal = (setModal: Dispatch<SetStateAction<ReactNode>>): void => {
const descriptor = useSubscription(imperativeModal);
useEffect(() => {
if (descriptor === null) {
return setModal(null);
}
// todo API to accept old modal props
// and return equivalent React modal
if ('options' in descriptor) {
return; // handleBlazeModal
}
if ('component' in descriptor) {
return setModal(createElement(descriptor.component, descriptor.props));
}
throw new Error('invalid modal descriptor');
}, [descriptor, setModal]);
const unsub = imperativeModal.on('update', (descriptor) => {
if (descriptor === null) {
return setModal(null);
}
if ('component' in descriptor) {
setModal(
createElement(descriptor.component, {
key: Math.random(),
...descriptor.props,
}),
);
}
});
return unsub;
}, [setModal]);
};

Loading…
Cancel
Save