Commit 36874166 authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Make sure profile modal is not added to the DOM until it's first opened

parent 49951bfe
import { useEffect, useRef, useState } from 'preact/hooks';
import classnames from 'classnames';
import { CancelIcon, IconButton } from '@hypothesis/frontend-shared/lib/next'; import { CancelIcon, IconButton } from '@hypothesis/frontend-shared/lib/next';
import classnames from 'classnames';
import { useEffect, useRef, useState } from 'preact/hooks';
import type { Emitter, EventBus } from '../util/emitter'; import type { Emitter, EventBus } from '../util/emitter';
...@@ -14,11 +14,15 @@ type ProfileModalProps = { ...@@ -14,11 +14,15 @@ type ProfileModalProps = {
export function ProfileModal({ eventBus, config }: ProfileModalProps) { export function ProfileModal({ eventBus, config }: ProfileModalProps) {
const [isHidden, setIsHidden] = useState(true); const [isHidden, setIsHidden] = useState(true);
const emitterRef = useRef<Emitter | null>(null); const emitterRef = useRef<Emitter | null>(null);
// Used only to track when was this modal first open, delaying the iframe to
// be loaded until strictly necessary.
const [hasOpened, setHasOpened] = useState(false);
useEffect(() => { useEffect(() => {
const emitter = eventBus.createEmitter(); const emitter = eventBus.createEmitter();
emitter.subscribe('openProfile', () => { emitter.subscribe('openProfile', () => {
setIsHidden(false); setIsHidden(false);
setHasOpened(true);
}); });
emitterRef.current = emitter; emitterRef.current = emitter;
...@@ -32,6 +36,10 @@ export function ProfileModal({ eventBus, config }: ProfileModalProps) { ...@@ -32,6 +36,10 @@ export function ProfileModal({ eventBus, config }: ProfileModalProps) {
emitterRef.current?.publish('closeProfile'); emitterRef.current?.publish('closeProfile');
}; };
if (!hasOpened) {
return null;
}
return ( return (
<div <div
className={classnames( className={classnames(
......
import { act } from 'preact/test-utils';
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import { act } from 'preact/test-utils';
import { EventBus } from '../../util/emitter'; import { EventBus } from '../../util/emitter';
import { ProfileModal } from '../ProfileModal'; import { ProfileModal } from '../ProfileModal';
...@@ -34,17 +34,15 @@ describe('ProfileModal', () => { ...@@ -34,17 +34,15 @@ describe('ProfileModal', () => {
components.forEach(component => component.unmount()); components.forEach(component => component.unmount());
}); });
it('hides modal on first render', () => { it('does not render anything before the modal has been opened at least once', () => {
const wrapper = createComponent(); const wrapper = createComponent();
const outer = wrapper.find(outerSelector); assert.equal(wrapper.find(outerSelector).length, 0);
assert.isTrue(outer.hasClass('hidden'));
}); });
it('shows modal on "openProfile" event', () => { it('shows modal on "openProfile" event', () => {
const wrapper = createComponent(); const wrapper = createComponent();
emitter.publish('openProfile', 'myGroup'); emitter.publish('openProfile');
wrapper.update(); wrapper.update();
const outer = wrapper.find(outerSelector); const outer = wrapper.find(outerSelector);
...@@ -57,7 +55,7 @@ describe('ProfileModal', () => { ...@@ -57,7 +55,7 @@ describe('ProfileModal', () => {
it('hides modal on closing', () => { it('hides modal on closing', () => {
const wrapper = createComponent(); const wrapper = createComponent();
emitter.publish('openProfile', 'myGroup'); emitter.publish('openProfile');
wrapper.update(); wrapper.update();
let outer = wrapper.find(outerSelector); let outer = wrapper.find(outerSelector);
......
...@@ -9,8 +9,8 @@ import { ...@@ -9,8 +9,8 @@ import {
} from '../shared/messaging'; } from '../shared/messaging';
import type { Destroyable } from '../types/annotator'; import type { Destroyable } from '../types/annotator';
import type { NotebookConfig } from './components/NotebookModal'; import type { NotebookConfig } from './components/NotebookModal';
import { getConfig } from './config/index';
import type { ProfileConfig } from './components/ProfileModal'; import type { ProfileConfig } from './components/ProfileModal';
import { getConfig } from './config/index';
import { Guest } from './guest'; import { Guest } from './guest';
import type { GuestConfig } from './guest'; import type { GuestConfig } from './guest';
import { import {
......
import { render } from 'preact'; import { render } from 'preact';
import type { Destroyable } from '../types/annotator'; import type { Destroyable } from '../types/annotator';
import type { ProfileConfig } from './components/ProfileModal'; import type { ProfileConfig } from './components/ProfileModal';
import { ProfileModal } from './components/ProfileModal'; import { ProfileModal } from './components/ProfileModal';
import type { EventBus } from './util/emitter'; import type { EventBus } from './util/emitter';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment