mirror of
				https://github.com/mathuo/dockview
				synced 2025-11-04 06:07:15 +00:00 
			
		
		
		
	Merge pull request #737 from mathuo/736-bug-set-initial-size-and-use-proper-window-on-event
736 bug set initial size and use proper window on event
This commit is contained in:
		
						commit
						408db93917
					
				
							
								
								
									
										35
									
								
								packages/dockview-core/src/__tests__/__mocks__/mockWindow.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								packages/dockview-core/src/__tests__/__mocks__/mockWindow.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
			
		||||
import { fromPartial } from "@total-typescript/shoehorn";
 | 
			
		||||
 | 
			
		||||
export function setupMockWindow() {
 | 
			
		||||
    const listeners: Record<string, (() => void)[]> = {};
 | 
			
		||||
 | 
			
		||||
    let width = 1000;
 | 
			
		||||
    let height = 2000;
 | 
			
		||||
 | 
			
		||||
    return fromPartial<Window>({
 | 
			
		||||
        addEventListener: (type: string, listener: () => void) => {
 | 
			
		||||
            if (!listeners[type]) {
 | 
			
		||||
                listeners[type] = [];
 | 
			
		||||
            }
 | 
			
		||||
            listeners[type].push(listener);
 | 
			
		||||
            if (type === 'load') {
 | 
			
		||||
                listener();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        dispatchEvent: (event: Event) => {
 | 
			
		||||
            const items = listeners[event.type];
 | 
			
		||||
            if (!items) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            items.forEach((item) => item());
 | 
			
		||||
        },
 | 
			
		||||
        document: document,
 | 
			
		||||
        close: jest.fn(),
 | 
			
		||||
        get innerWidth() {
 | 
			
		||||
            return width++;
 | 
			
		||||
        },
 | 
			
		||||
        get innerHeight() {
 | 
			
		||||
            return height++;
 | 
			
		||||
        },
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
@ -19,6 +19,8 @@ import {
 | 
			
		||||
import { fromPartial } from '@total-typescript/shoehorn';
 | 
			
		||||
import { DockviewApi } from '../../api/component.api';
 | 
			
		||||
import { DockviewDndOverlayEvent } from '../../dockview/options';
 | 
			
		||||
import { SizeEvent } from '../../api/gridviewPanelApi';
 | 
			
		||||
import { setupMockWindow } from '../__mocks__/mockWindow';
 | 
			
		||||
 | 
			
		||||
class PanelContentPartTest implements IContentRenderer {
 | 
			
		||||
    element: HTMLElement = document.createElement('div');
 | 
			
		||||
@ -115,7 +117,7 @@ describe('dockviewComponent', () => {
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        window.open = jest.fn(); // not implemented by jest
 | 
			
		||||
        window.open = jest.fn();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('update className', () => {
 | 
			
		||||
@ -4819,6 +4821,8 @@ describe('dockviewComponent', () => {
 | 
			
		||||
        test('add a popout group', async () => {
 | 
			
		||||
            const container = document.createElement('div');
 | 
			
		||||
 | 
			
		||||
            window.open = () => setupMockWindow();
 | 
			
		||||
 | 
			
		||||
            const dockview = new DockviewComponent(container, {
 | 
			
		||||
                createComponent(options) {
 | 
			
		||||
                    switch (options.name) {
 | 
			
		||||
@ -4850,12 +4854,36 @@ describe('dockviewComponent', () => {
 | 
			
		||||
            expect(dockview.groups.length).toBe(1);
 | 
			
		||||
            expect(dockview.panels.length).toBe(2);
 | 
			
		||||
 | 
			
		||||
            await dockview.addPopoutGroup(panel2.group);
 | 
			
		||||
            const events: SizeEvent[] = [];
 | 
			
		||||
 | 
			
		||||
            panel2.api.onDidDimensionsChange((event) => {
 | 
			
		||||
                events.push(event);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            const originalGroup = panel2.group;
 | 
			
		||||
 | 
			
		||||
            expect(await dockview.addPopoutGroup(panel2.group)).toBeTruthy();
 | 
			
		||||
 | 
			
		||||
            expect(events).toEqual([{ height: 2000, width: 1000 }]);
 | 
			
		||||
 | 
			
		||||
            expect(originalGroup.api.location.type).toBe('grid');
 | 
			
		||||
            expect(originalGroup.api.isVisible).toBeFalsy();
 | 
			
		||||
 | 
			
		||||
            expect(panel1.group.api.location.type).toBe('popout');
 | 
			
		||||
            expect(panel2.group.api.location.type).toBe('popout');
 | 
			
		||||
            expect(dockview.groups.length).toBe(2);
 | 
			
		||||
            expect(dockview.panels.length).toBe(2);
 | 
			
		||||
 | 
			
		||||
            if (panel2.api.location.type !== 'popout') {
 | 
			
		||||
                fail('unexpected');
 | 
			
		||||
            }
 | 
			
		||||
            const alternativeWindow = panel2.api.location.getWindow();
 | 
			
		||||
            alternativeWindow.dispatchEvent(new Event('resize'));
 | 
			
		||||
 | 
			
		||||
            expect(events).toEqual([
 | 
			
		||||
                { height: 2000, width: 1000 },
 | 
			
		||||
                { height: 2001, width: 1001 },
 | 
			
		||||
            ]);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        test('remove all panels from popout group', async () => {
 | 
			
		||||
@ -4894,7 +4922,7 @@ describe('dockviewComponent', () => {
 | 
			
		||||
                position: { referencePanel: panel2 },
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            await dockview.addPopoutGroup(panel2.group);
 | 
			
		||||
            expect(await dockview.addPopoutGroup(panel2.group)).toBeTruthy();
 | 
			
		||||
 | 
			
		||||
            expect(panel1.group.api.location.type).toBe('grid');
 | 
			
		||||
            expect(panel2.group.api.location.type).toBe('popout');
 | 
			
		||||
@ -4936,7 +4964,7 @@ describe('dockviewComponent', () => {
 | 
			
		||||
                component: 'default',
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            await dockview.addPopoutGroup(panel1);
 | 
			
		||||
            expect(await dockview.addPopoutGroup(panel1)).toBeTruthy();
 | 
			
		||||
 | 
			
		||||
            expect(dockview.panels.length).toBe(1);
 | 
			
		||||
            expect(dockview.groups.length).toBe(2);
 | 
			
		||||
@ -4991,7 +5019,7 @@ describe('dockviewComponent', () => {
 | 
			
		||||
            expect(dockview.groups.length).toBe(2);
 | 
			
		||||
            expect(dockview.panels.length).toBe(3);
 | 
			
		||||
 | 
			
		||||
            await dockview.addPopoutGroup(panel2.group);
 | 
			
		||||
            expect(await dockview.addPopoutGroup(panel2.group)).toBeTruthy();
 | 
			
		||||
 | 
			
		||||
            expect(panel1.group.api.location.type).toBe('popout');
 | 
			
		||||
            expect(panel2.group.api.location.type).toBe('popout');
 | 
			
		||||
 | 
			
		||||
@ -913,7 +913,7 @@ export class DockviewApi implements CommonApi<SerializedDockview> {
 | 
			
		||||
            onDidOpen?: (event: { id: string; window: Window }) => void;
 | 
			
		||||
            onWillClose?: (event: { id: string; window: Window }) => void;
 | 
			
		||||
        }
 | 
			
		||||
    ): Promise<void> {
 | 
			
		||||
    ): Promise<boolean> {
 | 
			
		||||
        return this.component.addPopoutGroup(item, options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -218,7 +218,7 @@ export interface IDockviewComponent extends IBaseGrid<DockviewGroupPanel> {
 | 
			
		||||
            onDidOpen?: (event: { id: string; window: Window }) => void;
 | 
			
		||||
            onWillClose?: (event: { id: string; window: Window }) => void;
 | 
			
		||||
        }
 | 
			
		||||
    ): Promise<void>;
 | 
			
		||||
    ): Promise<boolean>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class DockviewComponent
 | 
			
		||||
@ -548,7 +548,7 @@ export class DockviewComponent
 | 
			
		||||
            onWillClose?: (event: { id: string; window: Window }) => void;
 | 
			
		||||
            overridePopoutGroup?: DockviewGroupPanel;
 | 
			
		||||
        }
 | 
			
		||||
    ): Promise<void> {
 | 
			
		||||
    ): Promise<boolean> {
 | 
			
		||||
        if (
 | 
			
		||||
            itemToPopout instanceof DockviewPanel &&
 | 
			
		||||
            itemToPopout.group.size === 1
 | 
			
		||||
@ -579,10 +579,6 @@ export class DockviewComponent
 | 
			
		||||
        const groupId =
 | 
			
		||||
            options?.overridePopoutGroup?.id ?? this.getNextGroupId();
 | 
			
		||||
 | 
			
		||||
        if (itemToPopout.api.location.type === 'grid') {
 | 
			
		||||
            itemToPopout.api.setVisible(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const _window = new PopoutWindow(
 | 
			
		||||
            `${this.id}-${groupId}`, // unique id
 | 
			
		||||
            theme ?? '',
 | 
			
		||||
@ -608,12 +604,12 @@ export class DockviewComponent
 | 
			
		||||
            .open()
 | 
			
		||||
            .then((popoutContainer) => {
 | 
			
		||||
                if (_window.isDisposed) {
 | 
			
		||||
                    return;
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (popoutContainer === null) {
 | 
			
		||||
                    popoutWindowDisposable.dispose();
 | 
			
		||||
                    return;
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                const gready = document.createElement('div');
 | 
			
		||||
@ -635,6 +631,10 @@ export class DockviewComponent
 | 
			
		||||
                    options?.overridePopoutGroup ??
 | 
			
		||||
                    this.createGroup({ id: groupId });
 | 
			
		||||
                group.model.renderContainer = overlayRenderContainer;
 | 
			
		||||
                group.layout(
 | 
			
		||||
                    _window.window!.innerWidth,
 | 
			
		||||
                    _window.window!.innerHeight
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                if (!options?.overridePopoutGroup) {
 | 
			
		||||
                    this._onDidAddGroup.fire(group);
 | 
			
		||||
@ -676,6 +676,10 @@ export class DockviewComponent
 | 
			
		||||
                    getWindow: () => _window.window!,
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                if (itemToPopout.api.location.type === 'grid') {
 | 
			
		||||
                    itemToPopout.api.setVisible(false);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.doSetGroupAndPanelActive(group);
 | 
			
		||||
 | 
			
		||||
                popoutWindowDisposable.addDisposables(
 | 
			
		||||
@ -715,7 +719,10 @@ export class DockviewComponent
 | 
			
		||||
                        _window.window!,
 | 
			
		||||
                        'resize',
 | 
			
		||||
                        () => {
 | 
			
		||||
                            group.layout(window.innerWidth, window.innerHeight);
 | 
			
		||||
                            group.layout(
 | 
			
		||||
                                _window.window!.innerWidth,
 | 
			
		||||
                                _window.window!.innerHeight
 | 
			
		||||
                            );
 | 
			
		||||
                        }
 | 
			
		||||
                    ),
 | 
			
		||||
                    overlayRenderContainer,
 | 
			
		||||
@ -752,9 +759,12 @@ export class DockviewComponent
 | 
			
		||||
 | 
			
		||||
                this._popoutGroups.push(value);
 | 
			
		||||
                this.updateWatermark();
 | 
			
		||||
 | 
			
		||||
                return true;
 | 
			
		||||
            })
 | 
			
		||||
            .catch((err) => {
 | 
			
		||||
                console.error('dockview: failed to create popout window', err);
 | 
			
		||||
                return false;
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -124,7 +124,7 @@ export class PopoutWindow extends CompositeDisposable {
 | 
			
		||||
            window: externalWindow,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return new Promise<HTMLElement | null>((resolve) => {
 | 
			
		||||
        return new Promise<HTMLElement | null>((resolve, reject) => {
 | 
			
		||||
            externalWindow.addEventListener('unload', (e) => {
 | 
			
		||||
                // if page fails to load before unloading
 | 
			
		||||
                // this.close();
 | 
			
		||||
@ -135,6 +135,7 @@ export class PopoutWindow extends CompositeDisposable {
 | 
			
		||||
                 * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
 | 
			
		||||
                 */
 | 
			
		||||
 | 
			
		||||
                try {
 | 
			
		||||
                    const externalDocument = externalWindow.document;
 | 
			
		||||
                    externalDocument.title = document.title;
 | 
			
		||||
 | 
			
		||||
@ -158,6 +159,10 @@ export class PopoutWindow extends CompositeDisposable {
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                    resolve(container);
 | 
			
		||||
                } catch (err) {
 | 
			
		||||
                    // only except this is the DOM isn't setup. e.g. in a in correctly configured test
 | 
			
		||||
                    reject(err);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user