Browse Source

Add new window for DevToolbar, center PreloadWindow with MainWindow position

master
Loëck Vézien 7 years ago
parent
commit
3a0d18d2e1
No known key found for this signature in database GPG Key ID: CBCDCE384E853AC4
  1. 10
      src/components/App.js
  2. 114
      src/components/DevToolbar.js
  3. 6
      src/components/layout/Default.js
  4. 25
      src/components/layout/Dev.js
  5. 4
      src/components/layout/Print.js
  6. 1
      src/internals/index.js
  7. 119
      src/main/app.js
  8. 20
      src/main/bridge.js
  9. 6
      src/renderer/events.js
  10. 6
      src/renderer/index.js

10
src/components/App.js

@ -11,8 +11,9 @@ import theme from 'styles/theme'
import i18n from 'renderer/i18n'
import Wrapper from 'components/Wrapper'
import PrintWrapper from 'components/PrintWrapper'
import Default from 'components/layout/Default'
import Dev from 'components/layout/Dev'
import Print from 'components/layout/Print'
export default ({
store,
@ -28,8 +29,9 @@ export default ({
<ThemeProvider theme={theme}>
<ConnectedRouter history={history}>
<Switch>
<Route path="/print" component={PrintWrapper} />
<Route component={Wrapper} />
{__DEV__ && <Route path="/dev" component={Dev} />}
<Route path="/print" component={Print} />
<Route component={Default} />
</Switch>
</ConnectedRouter>
</ThemeProvider>

114
src/components/DevToolbar.js

@ -1,7 +1,7 @@
// @flow
import React, { PureComponent } from 'react'
import { ipcRenderer } from 'electron'
import { remote, ipcRenderer } from 'electron'
import { translate } from 'react-i18next'
import { AreaChart, Area } from 'recharts'
import takeRight from 'lodash/takeRight'
@ -10,15 +10,18 @@ import reduce from 'lodash/fp/reduce'
import flow from 'lodash/fp/flow'
import filter from 'lodash/fp/filter'
import sortBy from 'lodash/fp/sortBy'
import chunk from 'lodash/chunk'
import styled from 'styled-components'
import color from 'color'
import Box from 'components/base/Box'
import GrowScroll from 'components/base/GrowScroll'
import Bar from 'components/base/Bar'
import CopyToClipboard from 'components/base/CopyToClipboard'
import theme from 'styles/theme'
const mainWindow = remote.BrowserWindow.getAllWindows().find(w => w.name === 'MainWindow')
type HslColor = {
color: Array<number>,
}
@ -53,40 +56,16 @@ const colors: Array<ColorType> = transform(theme.colors)
const Container = styled(Box).attrs({
bg: 'night',
p: 1,
p: 5,
grow: true,
color: 'white',
fontSize: 0,
})`
position: fixed;
bottom: 0;
right: 0;
z-index: 1;
border-top-left-radius: 3px;
transition: ease-in-out transform 300ms;
transform: translate3d(0, ${p => (p.isOpened ? '0' : '100%')}, 0);
`
const Handle = styled(Box).attrs({
bg: 'night',
justify: 'center',
px: 1,
})`
cursor: pointer;
position: absolute;
bottom: 100%;
right: 5px;
font-size: 9px;
height: 20px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
`
fontSize: 3,
})``
const Colors = styled(Box).attrs({
horizontal: true,
align: 'flex-start',
})`
flex-wrap: wrap;
`
flow: 4,
})``
const Cl = styled(Box).attrs({
align: 'center',
@ -94,9 +73,8 @@ const Cl = styled(Box).attrs({
p: 2,
})`
border: 2px solid white;
flex: 1;
cursor: pointer;
margin: 2px;
width: 80px;
`
const Color = ({ onClick, color }: { onClick: Function, color: ColorType }) => (
@ -106,29 +84,22 @@ const Color = ({ onClick, color }: { onClick: Function, color: ColorType }) => (
)
const Lang = styled(Box).attrs({
bg: p => (p.current ? 'white' : 'night'),
color: p => (p.current ? 'night' : 'white'),
bg: 'night',
color: 'white',
borderColor: 'white',
borderWidth: 1,
p: 1,
borderWidth: 2,
borderRadius: 1,
p: 2,
})`
border-radius: 3px;
cursor: pointer;
`
const LANGUAGES = {
fr: 'français',
en: 'english',
}
type State = {
isOpened: boolean,
cpuUsage: Object,
}
class DevToolbar extends PureComponent<any, State> {
state = {
isOpened: false,
cpuUsage: {},
}
@ -159,32 +130,34 @@ class DevToolbar extends PureComponent<any, State> {
}
}
handleToggle = () => this.setState({ isOpened: !this.state.isOpened })
handleChangeLanguage = lang => () => this.props.i18n.changeLanguage(lang)
handleChangeLanguage = lang => () => {
mainWindow.webContents.send('msg', {
type: 'application.changeLanguage',
data: lang,
})
}
render() {
const { i18n } = this.props
const { isOpened, cpuUsage } = this.state
const { cpuUsage } = this.state
return (
<Container isOpened={isOpened}>
<Handle onClick={this.handleToggle}>{'DEV'}</Handle>
<Box horizontal grow flow={10}>
<Box flow={10}>
{Object.keys(LANGUAGES).map(lang => (
<Lang
key={lang}
current={i18n.language === lang}
onClick={this.handleChangeLanguage(lang)}
>
{LANGUAGES[lang]}
<Container>
<Box grow flow={4}>
<Box flow={4} horizontal>
{Object.keys(i18n.store.data).map(lang => (
<Lang key={lang} onClick={this.handleChangeLanguage(lang)}>
{lang}
</Lang>
))}
</Box>
<Box style={{ width: 168 }}>
<GrowScroll>
<Colors>
{colors.map(color => (
<Bar size={2} color="white" />
<Box flow={4}>
{chunk(colors, 8).map((c, i) => (
<Colors
key={i} // eslint-disable-line react/no-array-index-key
>
{c.map(color => (
<CopyToClipboard
key={color.name}
data={color.name}
@ -192,16 +165,17 @@ class DevToolbar extends PureComponent<any, State> {
/>
))}
</Colors>
</GrowScroll>
))}
</Box>
<Box flow={10}>
<Bar size={2} color="white" />
<Box flow={4} horizontal>
{Object.keys(cpuUsage)
.sort()
.map(k => (
<Box key={k} grow>
<Box horizontal align="center">
<Box grow>{k}</Box>
<Box fontSize="8px">{last(cpuUsage[k]).value}%</Box>
<Box key={k}>
<Box horizontal align="center" flow={2}>
<Box fontSize={1}>{last(cpuUsage[k]).value}%</Box>
<Box>{k}</Box>
</Box>
<Box>
<AreaChart

6
src/components/Wrapper.js → src/components/layout/Default.js

@ -15,7 +15,6 @@ import DashboardPage from 'components/DashboardPage'
import SettingsPage from 'components/SettingsPage'
import AppRegionDrag from 'components/AppRegionDrag'
import DevToolbar from 'components/DevToolbar'
import IsUnlocked from 'components/IsUnlocked'
import SideBar from 'components/SideBar'
import TopBar from 'components/TopBar'
@ -27,7 +26,7 @@ const Container = styled(GrowScroll).attrs({
padding-top: ${p => p.theme.sizes.topBarHeight + p.theme.space[7]}px;
`
class Wrapper extends Component<{}> {
class Default extends Component<{}> {
componentDidMount() {
window.requestAnimationFrame(
() => (this._timeout = setTimeout(() => ipcRenderer.send('app-finish-rendering'), 300)),
@ -44,7 +43,6 @@ class Wrapper extends Component<{}> {
return (
<Fragment>
{process.platform === 'darwin' && <AppRegionDrag />}
{__DEV__ && <DevToolbar />}
<IsUnlocked>
{Object.entries(modals).map(([name, ModalComponent]: [string, any]) => (
@ -70,4 +68,4 @@ class Wrapper extends Component<{}> {
}
}
export default translate()(Wrapper)
export default translate()(Default)

25
src/components/layout/Dev.js

@ -0,0 +1,25 @@
// @flow
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import Box from 'components/base/Box'
import DevToolbar from 'components/DevToolbar'
const Container = styled(Box).attrs({
grow: true,
})`
height: 100%;
`
class Dev extends PureComponent<{}> {
render() {
return (
<Container>
<DevToolbar />
</Container>
)
}
}
export default Dev

4
src/components/PrintWrapper.js → src/components/layout/Print.js

@ -12,7 +12,7 @@ type State = {
data: Object | null,
}
class PrintWrapper extends PureComponent<any, State> {
class Print extends PureComponent<any, State> {
state = {
data: null,
}
@ -49,4 +49,4 @@ class PrintWrapper extends PureComponent<any, State> {
}
}
export default PrintWrapper
export default Print

1
src/internals/index.js

@ -69,6 +69,7 @@ if (__DEV__) {
value: cpuPercent,
},
{
window: 'DevWindow',
kill: false,
},
)

119
src/main/app.js

@ -8,14 +8,15 @@ import db from 'helpers/db'
// necessary to prevent win from being garbage collected
let mainWindow
let devWindow
let preloadWindow
let forceClose = false
const devTools = __DEV__
const getWindowPosition = (height, width) => {
const { bounds } = screen.getPrimaryDisplay()
const getWindowPosition = (height, width, display = screen.getPrimaryDisplay()) => {
const { bounds } = display
return {
x: Math.ceil(bounds.x + (bounds.width - width) / 2),
@ -23,10 +24,35 @@ const getWindowPosition = (height, width) => {
}
}
const getDefaultUrl = () =>
__DEV__
? `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT || ''}`
: `file://${__dirname}/index.html`
const saveWindowSettings = window => {
window.on(
'resize',
debounce(() => {
const [width, height] = window.getSize()
db.setIn('settings', `window.${window.name}.dimensions`, { width, height })
}, 100),
)
window.on(
'move',
debounce(() => {
const [x, y] = window.getPosition()
db.setIn('settings', `window.${window.name}.positions`, { x, y })
}, 100),
)
}
const defaultWindowOptions = {
backgroundColor: '#fff',
webPreferences: {
devTools,
// Enable, among other things, the ResizeObserver
experimentalFeatures: true,
},
}
@ -34,8 +60,8 @@ function createMainWindow() {
const MIN_HEIGHT = 768
const MIN_WIDTH = 1024
const savedDimensions = db.getIn('settings', 'window.dimensions', {})
const savedPositions = db.getIn('settings', 'window.positions', null)
const savedDimensions = db.getIn('settings', 'window.MainWindow.dimensions', {})
const savedPositions = db.getIn('settings', 'window.MainWindow.positions', null)
const width = savedDimensions.width || MIN_WIDTH
const height = savedDimensions.height || MIN_HEIGHT
@ -54,23 +80,20 @@ function createMainWindow() {
minWidth: MIN_WIDTH,
minHeight: MIN_HEIGHT,
show: false,
webPreferences: {
...defaultWindowOptions.webPreferences,
// Enable, among other things, the ResizeObserver
experimentalFeatures: true,
},
}
const window = new BrowserWindow(windowOptions)
const url = __DEV__
? `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT || ''}`
: `file://${__dirname}/index.html`
window.name = 'MainWindow'
const url = getDefaultUrl()
if (devTools) {
window.webContents.openDevTools()
}
saveWindowSettings(window)
window.loadURL(url)
window.on('close', e => {
@ -83,22 +106,6 @@ function createMainWindow() {
}
})
window.on(
'resize',
debounce(() => {
const [width, height] = window.getSize()
db.setIn('settings', 'window.dimensions', { width, height })
}, 100),
)
window.on(
'move',
debounce(() => {
const [x, y] = window.getPosition()
db.setIn('settings', 'window.positions', { x, y })
}, 100),
)
window.webContents.on('devtools-opened', () => {
window.focus()
setImmediate(() => {
@ -109,16 +116,64 @@ function createMainWindow() {
return window
}
function createDevWindow() {
const MIN_HEIGHT = 400
const MIN_WIDTH = 600
const savedDimensions = db.getIn('settings', 'window.DevWindow.dimensions', {})
const savedPositions = db.getIn('settings', 'window.DevWindow.positions', null)
const width = savedDimensions.width || MIN_WIDTH
const height = savedDimensions.height || MIN_HEIGHT
const windowOptions = {
...defaultWindowOptions,
...(savedPositions !== null ? savedPositions : {}),
fullscreenable: false,
height,
show: false,
skipTaskbar: true,
width,
}
const window = new BrowserWindow(windowOptions)
window.name = 'DevWindow'
const url = getDefaultUrl()
if (devTools) {
window.webContents.openDevTools()
}
saveWindowSettings(window)
window.loadURL(`${url}/#/dev`)
window.on('ready-to-show', () => {
window.show()
})
return window
}
function createPreloadWindow() {
// Preload renderer of main windows
mainWindow = createMainWindow()
const [x, y] = mainWindow.getPosition()
if (__DEV__) {
devWindow = createDevWindow()
}
const height = 144
const width = 256
const windowOptions = {
...defaultWindowOptions,
...getWindowPosition(height, width),
...getWindowPosition(height, width, screen.getDisplayNearestPoint({ x, y })),
alwaysOnTop: true,
closable: false,
frame: false,
fullscreenable: false,
@ -131,6 +186,8 @@ function createPreloadWindow() {
const window = new BrowserWindow(windowOptions)
window.name = 'PreloadWindow'
window.loadURL(`file://${__static}/preload-window.html`)
window.on('ready-to-show', () => {
@ -197,4 +254,8 @@ ipcMain.on('app-finish-rendering', () => {
mainWindow.show()
setImmediate(() => mainWindow !== null && mainWindow.focus())
}
if (devWindow !== null) {
devWindow.show()
}
})

20
src/main/bridge.js

@ -1,7 +1,7 @@
// @flow
import { fork } from 'child_process'
import { ipcMain } from 'electron'
import { BrowserWindow, ipcMain } from 'electron'
import objectPath from 'object-path'
import { resolve } from 'path'
@ -34,11 +34,17 @@ function onForkChannel(forkType, callType) {
const onMessage = payload => {
const { type, data, options = {} } = payload
if (callType === 'async') {
event.sender.send('msg', { type, data })
}
if (callType === 'sync') {
event.returnValue = { type, data }
if (options.window) {
const devWindow = BrowserWindow.getAllWindows().find(w => w.name === options.window)
devWindow.webContents.send('msg', { type, data })
} else {
if (callType === 'async') {
event.sender.send('msg', { type, data })
}
if (callType === 'sync') {
event.returnValue = { type, data }
}
}
if (options.kill && compute) {
kill()
@ -72,5 +78,5 @@ ipcMain.on('msg', (event: any, payload) => {
return
}
const send = (type: string, data: *) => event.sender.send('msg', { type, data })
handler(send, data)
handler(send, data, type)
})

6
src/renderer/events.js

@ -14,6 +14,8 @@ import { updateAccount } from 'actions/accounts'
import { setUpdateStatus } from 'reducers/update'
import { getAccountData, getAccounts } from 'reducers/accounts'
import i18n from 'renderer/i18n'
const { DISABLED_SYNC, DISABLED_AUTO_SYNC } = process.env
type MsgPayload = {
@ -64,6 +66,10 @@ export function checkUpdates() {
export default ({ store, locked }: { store: Object, locked: boolean }) => {
const handlers = {
dispatch: (type, payload) => store.dispatch({ type, payload }),
application: {
changeLanguage: lang => i18n.changeLanguage(lang),
},
account: {
sync: {
success: account => {

6
src/renderer/index.js

@ -4,6 +4,7 @@ import 'env'
import React from 'react'
import Raven from 'raven-js'
import { remote } from 'electron'
import { render } from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import createHistory from 'history/createHashHistory'
@ -35,8 +36,6 @@ const history = createHistory()
const store = createStore(history)
const rootNode = document.getElementById('app')
global.__PRINT_MODE__ = history.location.pathname.startsWith('/print')
store.dispatch(fetchSettings())
const state = store.getState() || {}
@ -55,7 +54,8 @@ function r(Comp) {
r(<App store={store} history={history} language={language} />)
if (!__PRINT_MODE__) {
// Only init events on MainWindow
if (remote.getCurrentWindow().name === 'MainWindow') {
events({ store, locked })
}

Loading…
Cancel
Save