feat: add tab button to duplicate currently selected window by sentialx · Pull Request #104 · sentialx/multrin · GitHub
Skip to content
This repository was archived by the owner on Jun 23, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
34 changes: 19 additions & 15 deletions src/main/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ export class Container {

private appWindow: AppWindow;

public constructor(appWindow: AppWindow, window: ProcessWindow) {
public constructor(
appWindow: AppWindow,
window: ProcessWindow,
dragged = true,
) {
this.appWindow = appWindow;

const colId = spaceId++;
Expand All @@ -50,7 +54,7 @@ export class Container {

window.rowId = rowId;
window.columnId = colId;
window.dragged = true;
window.dragged = dragged;

this.windows.push(window);

Expand Down Expand Up @@ -88,7 +92,7 @@ export class Container {
top += row.height;

const window = this.windows.find(
x => x.rowId === row.id && x.columnId === col.id,
(x) => x.rowId === row.id && x.columnId === col.id,
);

if (window && !window.dragged && !window.resizing) {
Expand All @@ -107,26 +111,26 @@ export class Container {
}

public removeWindow(id: number, mouseup = true) {
const win = this.windows.find(x => x.id === id);
const win = this.windows.find((x) => x.id === id);
if (!win) return;

const col = this.columns.find(x => x.id === win.columnId);
const col = this.columns.find((x) => x.id === win.columnId);
if (!col) return;

let winDetached = false;

if (col.rows.length === 1) {
this.columns = this.columns.filter(x => x.id !== win.columnId);
this.columns = this.columns.filter((x) => x.id !== win.columnId);
this.detachWindow(win, mouseup);
winDetached = true;
}

if (!col) return;

const row = col.rows.find(x => x.id === win.rowId);
const row = col.rows.find((x) => x.id === win.rowId);
if (!row) return;

col.rows = col.rows.filter(x => x.id !== win.rowId);
col.rows = col.rows.filter((x) => x.id !== win.rowId);
if (!winDetached) {
this.detachWindow(win, mouseup);
}
Expand All @@ -147,7 +151,7 @@ export class Container {

window.detach(mouseup);

this.windows = this.windows.filter(x => x.id !== window.id);
this.windows = this.windows.filter((x) => x.id !== window.id);

if (this.windows.length === 0) {
this.appWindow.removeContainer(this);
Expand All @@ -156,15 +160,15 @@ export class Container {

public dragWindow(window: ProcessWindow, { x, y, type }: any) {
const area = this.appWindow.getContentArea();
const win = this.windows.find(x => x.id === window.id);
const win = this.windows.find((x) => x.id === window.id);

if (win) {
if (win.resizing) return;

const col = this.columns.find(x => x.id === win.columnId);
const col = this.columns.find((x) => x.id === win.columnId);
if (!col) return;

const row = col.rows.find(x => x.id === win.rowId);
const row = col.rows.find((x) => x.id === win.rowId);

win.dragged = true;

Expand Down Expand Up @@ -261,10 +265,10 @@ export class Container {
}

public resizeWindow(window: ProcessWindow, resizeWinCb: () => void) {
const win = this.windows.find(x => x.id === window.id);
const win = this.windows.find((x) => x.id === window.id);
if (!win) return;

const col = this.columns.find(x => x.id === win.columnId);
const col = this.columns.find((x) => x.id === win.columnId);
if (!col) return;

const winBounds = win.getBounds();
Expand All @@ -290,7 +294,7 @@ export class Container {
c.weight = c.width / baseWidth;
}
} else if (winBounds.height !== win.lastBounds.height) {
const row = col.rows.find(x => x.id === win.rowId);
const row = col.rows.find((x) => x.id === win.rowId);
if (!row) return;

const index = winBounds.y !== win.lastBounds.y ? -1 : 1;
Expand Down
141 changes: 92 additions & 49 deletions src/main/windows/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ export class AppWindow extends BrowserWindow {
this.selectContainer(this.containers.find((x) => x.id === id));
});

ipcMain.on('new-tab', () => {
this.newTab();
});

ipcMain.on('detach-window', (e, id: number) => {
for (const container of this.containers) {
container.removeWindow(id, true);
Expand Down Expand Up @@ -241,29 +245,7 @@ export class AppWindow extends BrowserWindow {
this.draggedWindow.resizing = false;

if (this.willAttachWindow) {
const win = this.draggedWindow;
const container = this.draggedContainer;

if (platform() === 'win32') {
const handle = this.getNativeWindowHandle().readInt32LE(0);
win.setOwner(handle);
}

if (platform() === 'darwin' && this.containers.length === 0) {
this.setBounds({ height: TOOLBAR_HEIGHT } as any);
this.setMaximumSize(0, TOOLBAR_HEIGHT);
}

this.containers.push(this.draggedContainer);
this.willAttachWindow = false;

this.draggedContainer.rearrangeWindows();

setTimeout(() => {
this.selectContainer(container);
}, 50);

this.controlShortcuts(win.id);
this.attachNewContainer(this.draggedContainer, this.draggedWindow);
} else if (this.willSplitWindow && !this.detached) {
this.willSplitWindow = false;

Expand Down Expand Up @@ -420,34 +402,9 @@ export class AppWindow extends BrowserWindow {
this.selectedContainer.removeWindow(win.id, e.type === 'mouseup');
}

const container = new Container(this, win);

const title = this.draggedWindow.getTitle();
const container = this.prepareContainer(this.draggedWindow);

this.draggedContainer = container;
win.lastTitle = title;

const icon = fileIcon(win.path, 16);

this.webContents.send('add-tab', {
id: container.id,
title,
icon,
});

try {
Vibrant.from(icon)
.getPalette()
.then((palette) => {
this.webContents.send(
'tab-background',
container.id,
palette.Vibrant.hex,
);
});
} catch (e) {
console.error(e);
}

this.draggedIn = true;
this.willAttachWindow = true;
Expand All @@ -461,6 +418,92 @@ export class AppWindow extends BrowserWindow {
}
}

public prepareContainer(window: ProcessWindow, dragged = true) {
const container = new Container(this, window, dragged);

const title = window.getTitle();
const icon = fileIcon(window.path, 16);

window.lastTitle = title;

this.webContents.send('add-tab', {
id: container.id,
title,
icon,
});

try {
Vibrant.from(icon)
.getPalette()
.then((palette) => {
this.webContents.send(
'tab-background',
container.id,
palette.Vibrant.hex,
);
});
} catch (e) {
console.error(e);
}

return container;
}

public attachNewContainer(container: Container, win: ProcessWindow) {
if (platform() === 'win32') {
const handle = this.getNativeWindowHandle().readInt32LE(0);
win.setOwner(handle);
}

if (platform() === 'darwin' && this.containers.length === 0) {
this.setBounds({ height: TOOLBAR_HEIGHT } as any);
this.setMaximumSize(0, TOOLBAR_HEIGHT);
}

this.containers.push(container);
this.willAttachWindow = false;

container.rearrangeWindows();

setTimeout(() => {
this.selectContainer(container);
}, 50);

this.controlShortcuts(win.id);
}

public async newTab() {
if (this.selectedContainer?.windows?.length === 1) {
const window = await this.createNewWindow(
this.selectedContainer.windows[0].path,
);

this.addTabWithWindow(window);
}
}

public createNewWindow(path: string): Promise<ProcessWindow> {
return new Promise((resolve, reject) => {
windowManager.createProcess(path);

const timeout = setTimeout(() => {
reject(new Error('Creating new window timed out'));
}, 5000);

windowManager.once('window-activated', (win: ProcessWindow) => {
if (win.path === path) {
clearTimeout(timeout);
resolve(new ProcessWindow(win.id, this));
}
});
});
}

public addTabWithWindow(win: ProcessWindow) {
const container = this.prepareContainer(win, false);
this.attachNewContainer(container, win);
}

public getContentArea() {
const bounds = this.getContentBounds();

Expand Down
12 changes: 11 additions & 1 deletion src/renderer/views/app/components/Tabbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@ import * as React from 'react';

import HorizontalScrollbar from '../HorizontalScrollbar';
import store from '~/renderer/views/app/store';
import { StyledTabbar, TabsContainer } from './style';
import { StyledTabbar, TabsContainer, AddTab } from './style';
import { Tabs } from '../Tabs';
import { icons } from '../../constants';

const getContainer = () => store.tabsStore.containerRef.current;

const onMouseEnter = () => (store.tabsStore.scrollbarVisible = true);

const onMouseLeave = () => (store.tabsStore.scrollbarVisible = false);

const onAddTabClick = () => {
store.tabsStore.newTab();
};

export const Tabbar = observer(() => {
return (
<StyledTabbar>
Expand All @@ -22,6 +27,11 @@ export const Tabbar = observer(() => {
>
<Tabs />
</TabsContainer>
<AddTab
icon={icons.add}
onClick={onAddTabClick}
divRef={(r: any) => (store.addTab.ref = r)}
/>
<HorizontalScrollbar
ref={store.tabsStore.scrollbarRef}
enabled={store.tabsStore.scrollable}
Expand Down
49 changes: 28 additions & 21 deletions src/renderer/views/app/components/Tabbar/style.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
import styled from 'styled-components';

export const StyledTabbar = styled.div`
height: 100%;
width: 100%;
position: relative;
overflow: hidden;
transition: 0.3s opacity, 0.3s transform;
margin-right: 32px;
display: flex;
`;

export const TabsContainer = styled.div`
height: 100%;
width: 100%;
position: relative;
overflow: hidden;
white-space: nowrap;
display: flex;
align-items: center;
`;
import styled from 'styled-components';
import { ToolbarButton } from '../ToolbarButton';
import { TOOLBAR_BUTTON_WIDTH } from '../../constants';

export const StyledTabbar = styled.div`
height: 100%;
width: 100%;
position: relative;
overflow: hidden;
transition: 0.3s opacity, 0.3s transform;
margin-right: 32px;
display: flex;
`;

export const TabsContainer = styled.div`
height: 100%;
width: calc(100% - ${TOOLBAR_BUTTON_WIDTH}px);
position: relative;
overflow: hidden;
white-space: nowrap;
display: flex;
align-items: center;
`;

export const AddTab = styled(ToolbarButton)`
position: absolute;
left: 0;
`;
17 changes: 9 additions & 8 deletions src/renderer/views/app/constants/icons.ts
Loading