Skip to content
This repository has been archived by the owner on Jun 4, 2023. It is now read-only.

Commit

Permalink
Merge pull request #346 from wexond/tabs-preview
Browse files Browse the repository at this point in the history
feat: add tabs preview
  • Loading branch information
sentialx authored Nov 9, 2019
2 parents 50d342f + f94951d commit c6994dc
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/main/dialogs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './auth';
export * from './permissions';
export * from './form-fill';
export * from './credentials';
export * from './preview';
48 changes: 48 additions & 0 deletions src/main/dialogs/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { AppWindow } from '../windows';
import { MENU_WIDTH } from '~/constants/design';
import { Dialog } from '.';
import { TAB_MAX_WIDTH } from '~/renderer/views/app/constants/tabs';

const WIDTH = MENU_WIDTH;
const HEIGHT = 128;

export class PreviewDialog extends Dialog {
public visible = false;
public tab: { id?: number; x?: number } = {};

constructor(appWindow: AppWindow) {
super(appWindow, {
name: 'preview',
bounds: {
width: TAB_MAX_WIDTH + 16,
height: HEIGHT,
y: 40,
},
hideTimeout: 300,
});
}

public show() {
this.bounds.x = Math.round(this.tab.x - 8);

super.show();

const tab = this.appWindow.viewManager.views.find(
x => x.webContents.id === this.tab.id,
);

const url = tab.webContents.getURL();
const title = tab.webContents.getTitle();

this.webContents.send('visible', true, {
id: tab.id,
url: url.startsWith('wexond-error') ? tab.errorURL : url,
title,
});
}

public hide() {
super.hide();
this.webContents.send('visible', false);
}
}
9 changes: 9 additions & 0 deletions src/main/services/messaging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ export const runMessagingService = (appWindow: AppWindow) => {
appWindow.searchDialog.toggle();
});

ipcMain.on(`show-tab-preview-${id}`, (e, tab) => {
appWindow.previewDialog.tab = tab;
appWindow.previewDialog.show();
});

ipcMain.on(`hide-tab-preview-${id}`, (e, tab) => {
appWindow.previewDialog.hide();
});

ipcMain.on(`update-find-info-${id}`, (e, tabId, data) =>
appWindow.findDialog.updateInfo(tabId, data),
);
Expand Down
4 changes: 4 additions & 0 deletions src/main/windows/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
AuthDialog,
FormFillDialog,
CredentialsDialog,
PreviewDialog,
} from '../dialogs';

export class AppWindow extends BrowserWindow {
Expand All @@ -27,6 +28,7 @@ export class AppWindow extends BrowserWindow {
public authDialog = new AuthDialog(this);
public formFillDialog = new FormFillDialog(this);
public credentialsDialog = new CredentialsDialog(this);
public previewDialog = new PreviewDialog(this);

public incognito: boolean;

Expand Down Expand Up @@ -136,6 +138,7 @@ export class AppWindow extends BrowserWindow {
this.formFillDialog.destroy();
this.credentialsDialog.destroy();
this.permissionsDialog.destroy();
this.previewDialog.destroy();

this.menuDialog = null;
this.searchDialog = null;
Expand All @@ -144,6 +147,7 @@ export class AppWindow extends BrowserWindow {
this.formFillDialog = null;
this.credentialsDialog = null;
this.permissionsDialog = null;
this.previewDialog = null;

this.viewManager.clear();

Expand Down
11 changes: 8 additions & 3 deletions src/renderer/views/app/components/Toolbar/Tab/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
StyledIcon,
StyledTitle,
StyledClose,
StyledBorder,
StyledOverlay,
TabContainer,
} from './style';
Expand Down Expand Up @@ -47,10 +46,17 @@ const onMouseDown = (tab: ITab) => (e: React.MouseEvent<HTMLDivElement>) => {
store.tabs.lastScrollLeft = store.tabs.containerRef.current.scrollLeft;
};

const onMouseEnter = (tab: ITab) => () => {
const onMouseEnter = (tab: ITab) => (e: React.MouseEvent<HTMLDivElement>) => {
if (!store.tabs.isDragging) {
store.tabs.hoveredTabId = tab.id;
}

const x = e.currentTarget.getBoundingClientRect().left;

ipcRenderer.send(`show-tab-preview-${store.windowId}`, {
id: tab.id,
x,
});
};

const onMouseLeave = () => {
Expand Down Expand Up @@ -232,7 +238,6 @@ export default observer(({ tab }: { tab: ITab }) => {
onMouseLeave={onMouseLeave}
visible={tab.tabGroupId === store.tabGroups.currentGroupId}
ref={tab.ref}
title={tab.title}
>
<TabContainer
pinned={tab.isPinned}
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/views/app/components/Toolbar/Tabbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Tabs } from '../Tabs';
import store from '../../../store';
import { icons } from '~/renderer/constants';
import HorizontalScrollbar from '~/renderer/components/HorizontalScrollbar';
import { ipcRenderer } from 'electron';

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

Expand All @@ -16,12 +17,13 @@ const onMouseEnter = () => {
clearTimeout(timeout);
};

const onTabsMouseLeave = () => {
const onTabsMouseLeave = (e: React.MouseEvent) => {
store.tabs.scrollbarVisible = false;
timeout = setTimeout(() => {
store.tabs.removedTabs = 0;
store.tabs.updateTabsBounds(true);
}, 300);
ipcRenderer.send(`hide-tab-preview-${store.windowId}`);
};

const onAddTabClick = () => {
Expand Down
24 changes: 24 additions & 0 deletions src/renderer/views/preview/components/App/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as React from 'react';
import { observer } from 'mobx-react-lite';
import { createGlobalStyle, ThemeProvider } from 'styled-components';
import { hot } from 'react-hot-loader/root';

import { Style } from '../../style';
import { StyledApp, Title, Domain } from './style';
import store from '../../store';

const GlobalStyle = createGlobalStyle`${Style}`;

export const App = hot(
observer(() => {
return (
<ThemeProvider theme={{ ...store.theme }}>
<StyledApp visible={store.visible}>
<Title>{store.title}</Title>
<Domain>{store.domain}</Domain>
<GlobalStyle />
</StyledApp>
</ThemeProvider>
);
}),
);
45 changes: 45 additions & 0 deletions src/renderer/views/preview/components/App/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import styled, { css } from 'styled-components';
import { ITheme } from '~/interfaces';
import { maxLines } from '~/renderer/mixins';

export const StyledApp = styled.div`
margin: 8px;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
border-radius: 6px;
overflow: hidden;
position: relative;
transition: 0.2s opacity, 0.2s margin-top;
padding: 16px;
font-size: 14px;
${({ visible, theme }: { visible: boolean; theme?: ITheme }) => css`
opacity: ${visible ? 1 : 0};
margin-top: ${visible ? 0 : 7}px;
background-color: ${theme['dialog.backgroundColor']};
color: ${theme['dialog.textColor']};
`}
`;

export const Title = styled.div`
font-weight: 500;
line-height: 1.3rem;
${maxLines(2)};
`;

export const Domain = styled.div`
opacity: 0.54;
font-weight: 300;
line-height: 1.3rem;
`;

export const Subtitle = styled.div`
font-size: 13px;
opacity: 0.54;
margin-top: 8px;
`;

export const Buttons = styled.div`
display: flex;
margin-top: 16px;
float: right;
`;
35 changes: 35 additions & 0 deletions src/renderer/views/preview/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';

import { App } from './components/App';
import { fonts } from '../../constants';
import { ipcRenderer } from 'electron';

ipcRenderer.setMaxListeners(0);

const styleElement = document.createElement('style');

styleElement.textContent = `
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(${fonts.robotoRegular}) format('woff2');
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: url(${fonts.robotoMedium}) format('woff2');
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
src: url(${fonts.robotoLight}) format('woff2');
}
`;

document.head.appendChild(styleElement);

ReactDOM.render(<App />, document.getElementById('app'));
58 changes: 58 additions & 0 deletions src/renderer/views/preview/store/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { ipcRenderer, remote } from 'electron';
import { observable, computed } from 'mobx';
import { getTheme } from '~/utils/themes';
import { ISettings } from '~/interfaces';
import { DEFAULT_SETTINGS } from '~/constants';
import { parse } from 'url';

export class Store {
@observable
public settings: ISettings = DEFAULT_SETTINGS;

@computed
public get theme() {
return getTheme(this.settings.theme);
}

@observable
public visible = false;

@observable
public id = remote.getCurrentWebContents().id;

@observable
public windowId = remote.getCurrentWindow().id;

@observable
public title = '';

@observable
public url = '';

@computed
public get domain() {
return parse(this.url).hostname;
}

public constructor() {
ipcRenderer.on('visible', (e, flag, tab) => {
this.visible = flag;
if (tab) {
this.title = tab.title;
this.url = tab.url;
}
});

ipcRenderer.send('get-settings');

ipcRenderer.on('update-settings', (e, settings: ISettings) => {
this.settings = { ...this.settings, ...settings };
});
}

public hide() {
ipcRenderer.send(`hide-${this.id}`);
}
}

export default new Store();
20 changes: 20 additions & 0 deletions src/renderer/views/preview/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { css } from 'styled-components';

import { body2 } from '~/renderer/mixins';

export const Style = css`
body {
user-select: none;
cursor: default;
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
${body2()}
}
* {
box-sizing: border-box;
}
`;
1 change: 1 addition & 0 deletions webpack.config.renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ applyEntries('app', appConfig, [
'find',
'menu',
'search',
'preview',
]);

module.exports = appConfig;

0 comments on commit c6994dc

Please sign in to comment.