Commit 4a40015b authored by Luke Schoen's avatar Luke Schoen
Browse files

merge latest from master and fix conflicts

parent 0418e87f
Pipeline #31622 passed with stage
in 1 minute and 48 seconds
...@@ -18,17 +18,6 @@ export default async (fetherApp, event, action, ...args) => { ...@@ -18,17 +18,6 @@ export default async (fetherApp, event, action, ...args) => {
return; return;
} }
switch (action) { switch (action) {
case 'app-resize': {
if (!fetherApp.win || !args[0]) {
return;
}
const [width] = fetherApp.win.getContentSize();
// Conversion to integer is required to pass as argument to setContentSize.
// Reference: https://electronjs.org/docs/all#winsetcontentsizewidth-height-animate
const newHeight = parseInt(args[0]);
fetherApp.win.setContentSize(width, Math.round(newHeight) + 2);
break;
}
case 'app-right-click': { case 'app-right-click': {
if (!fetherApp.win) { if (!fetherApp.win) {
return; return;
......
...@@ -8,13 +8,7 @@ import Pino from '../utils/pino'; ...@@ -8,13 +8,7 @@ import Pino from '../utils/pino';
const pino = Pino(); const pino = Pino();
function setupWin32Listeners (fetherApp) { function setupWin32Listeners (fetherApp) {
const { const { onWindowClose, processSaveWinPosition, win } = fetherApp;
moveWindowUp,
onWindowClose,
processSaveWinPosition,
showTrayBalloon,
win
} = fetherApp;
if (process.platform === 'win32') { if (process.platform === 'win32') {
/** /**
...@@ -52,7 +46,6 @@ function setupWin32Listeners (fetherApp) { ...@@ -52,7 +46,6 @@ function setupWin32Listeners (fetherApp) {
} else if (wParam.readUInt32LE(0) === 0xf030) { } else if (wParam.readUInt32LE(0) === 0xf030) {
// SC_MAXIMIZE // SC_MAXIMIZE
eventName = 'maximize'; eventName = 'maximize';
showTrayBalloon(fetherApp);
} else if (wParam.readUInt32LE(0) === 0xf020) { } else if (wParam.readUInt32LE(0) === 0xf020) {
// SC_MINIMIZE // SC_MINIMIZE
eventName = 'minimize'; eventName = 'minimize';
...@@ -60,7 +53,6 @@ function setupWin32Listeners (fetherApp) { ...@@ -60,7 +53,6 @@ function setupWin32Listeners (fetherApp) {
} else if (wParam.readUInt32LE(0) === 0xf120) { } else if (wParam.readUInt32LE(0) === 0xf120) {
// SC_RESTORE // SC_RESTORE
eventName = 'restored'; eventName = 'restored';
showTrayBalloon(fetherApp);
} }
if (eventName !== null) { if (eventName !== null) {
...@@ -74,17 +66,7 @@ function setupWin32Listeners (fetherApp) { ...@@ -74,17 +66,7 @@ function setupWin32Listeners (fetherApp) {
* Detect event on Windows when Fether window was moved or resized * Detect event on Windows when Fether window was moved or resized
*/ */
win.hookWindowMessage(Number.parseInt('0x0232'), (wParam, lParam) => { win.hookWindowMessage(Number.parseInt('0x0232'), (wParam, lParam) => {
pino.info('Detected completion of move or resize event'); pino.info('Detected completion of moved or resize event');
// Move Fether window back up into view if it was a resize event
// that causes the bottom to be cropped
moveWindowUp(fetherApp);
// Try again after a delay incase Fether window resize occurs
// x seconds after navigating to a new page.
setTimeout(() => {
moveWindowUp(fetherApp);
}, 5000);
// Save Fether window position to Electron settings // Save Fether window position to Electron settings
processSaveWinPosition(fetherApp); processSaveWinPosition(fetherApp);
......
...@@ -11,12 +11,7 @@ import Pino from '../utils/pino'; ...@@ -11,12 +11,7 @@ import Pino from '../utils/pino';
const pino = Pino(); const pino = Pino();
function setupWinListeners (fetherApp) { function setupWinListeners (fetherApp) {
const { const { onWindowClose, processSaveWinPosition, win } = fetherApp;
moveWindowUp,
onWindowClose,
processSaveWinPosition,
win
} = fetherApp;
// Open external links in browser // Open external links in browser
win.webContents.on('new-window', (event, url) => { win.webContents.on('new-window', (event, url) => {
...@@ -24,7 +19,7 @@ function setupWinListeners (fetherApp) { ...@@ -24,7 +19,7 @@ function setupWinListeners (fetherApp) {
electron.shell.openExternal(url); electron.shell.openExternal(url);
}); });
// Linux (unchecked on others) // Windows and Linux (unchecked on others)
win.on('move', () => { win.on('move', () => {
/** /**
* On Linux using this with debouncing is the closest equivalent * On Linux using this with debouncing is the closest equivalent
...@@ -49,17 +44,12 @@ function setupWinListeners (fetherApp) { ...@@ -49,17 +44,12 @@ function setupWinListeners (fetherApp) {
* On Linux the closest equivalent to achieving 'moved' is debouncing * On Linux the closest equivalent to achieving 'moved' is debouncing
* on the 'move' event. It also works in 'close' even when app crashes * on the 'move' event. It also works in 'close' even when app crashes
*/ */
processSaveWinPosition(fetherApp); pino.info('Detected moved event');
}); });
// macOS and Linux (not Windows) // macOS and Linux and Windows
win.on('resize', () => { win.on('resize', () => {
pino.info('Detected resize event'); pino.info('Detected resize event');
moveWindowUp(fetherApp);
setTimeout(() => {
moveWindowUp(fetherApp);
}, 5000);
}); });
win.on('blur', () => { win.on('blur', () => {
......
...@@ -16,6 +16,8 @@ function showWindow (fetherApp, trayPos) { ...@@ -16,6 +16,8 @@ function showWindow (fetherApp, trayPos) {
calculateWinPosition, calculateWinPosition,
createWindow, createWindow,
fixWinPosition, fixWinPosition,
moveWindowUp,
processSaveWinPosition,
setupWinListeners, setupWinListeners,
setupWin32Listeners, setupWin32Listeners,
win win
...@@ -84,6 +86,13 @@ function showWindow (fetherApp, trayPos) { ...@@ -84,6 +86,13 @@ function showWindow (fetherApp, trayPos) {
fetherApp.hasSetupWinListeners = true; fetherApp.hasSetupWinListeners = true;
} }
moveWindowUp(fetherApp);
setTimeout(() => {
moveWindowUp(fetherApp);
}, 5000);
processSaveWinPosition(fetherApp);
fetherApp.emit('after-show-window'); fetherApp.emit('after-show-window');
} }
......
...@@ -17,7 +17,7 @@ const INDEX_HTML_PATH = ...@@ -17,7 +17,7 @@ const INDEX_HTML_PATH =
}); });
// Icon path differs when started with `yarn electron` or `yarn start` // Icon path differs when started with `yarn electron` or `yarn start`
let iconPath = path.join(staticPath, 'assets', 'icons', 'icon.png'); let iconPath = path.join(staticPath, 'assets', 'icons', 'mac', 'iconDock.png');
let iconDockPath = ''; let iconDockPath = '';
if (process.platform === 'win32') { if (process.platform === 'win32') {
...@@ -71,7 +71,7 @@ const DEFAULT_OPTIONS = { ...@@ -71,7 +71,7 @@ const DEFAULT_OPTIONS = {
const TASKBAR_OPTIONS = { const TASKBAR_OPTIONS = {
frame: false, frame: false,
height: 464, height: 515,
// On Linux the user must click the tray icon and then click the tooltip // On Linux the user must click the tray icon and then click the tooltip
// to toggle the Fether window open/close // to toggle the Fether window open/close
tooltip: tooltip, tooltip: tooltip,
......
...@@ -68,7 +68,8 @@ ...@@ -68,7 +68,8 @@
"react-router-dom": "^4.2.2", "react-router-dom": "^4.2.2",
"react-scripts": "^2.1.3", "react-scripts": "^2.1.3",
"recompose": "^0.27.1", "recompose": "^0.27.1",
"rxjs": "^6.2.0" "rxjs": "^6.2.0",
"semver": "^5.6.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-decorators": "^7.2.0", "@babel/plugin-proposal-decorators": "^7.2.0",
......
...@@ -90,7 +90,6 @@ class AccountsList extends Component { ...@@ -90,7 +90,6 @@ class AccountsList extends Component {
)} )}
</div> </div>
</div> </div>
<nav className='footer-nav'> <nav className='footer-nav'>
<div className='footer-nav_status'> <div className='footer-nav_status'>
<Health /> <Health />
......
...@@ -11,7 +11,6 @@ export const Feedback = ({ accountsListLength }) => ( ...@@ -11,7 +11,6 @@ export const Feedback = ({ accountsListLength }) => (
href='https://github.com/paritytech/fether/issues/new' href='https://github.com/paritytech/fether/issues/new'
rel='noopener noreferrer' rel='noopener noreferrer'
target='_blank' target='_blank'
style={{ marginBottom: accountsListLength > 1 ? '-2px' : '-10px' }}
> >
Feedback Feedback
</a> </a>
......
...@@ -168,7 +168,7 @@ class AccountImportOptions extends Component { ...@@ -168,7 +168,7 @@ class AccountImportOptions extends Component {
{importingFromSigner ? ( {importingFromSigner ? (
<Scanner <Scanner
onScan={this.handleSignerImported} onScan={this.handleSignerImported}
label='Please show the QR code of the account on the webcam.' label='Scan Parity Signer account QR code'
/> />
) : ( ) : (
<button <button
...@@ -203,15 +203,16 @@ class AccountImportOptions extends Component { ...@@ -203,15 +203,16 @@ class AccountImportOptions extends Component {
</Card> </Card>
); );
const spacer = <div style={{ height: '0.5rem' }} />;
return ( return (
<RequireHealthOverlay require='node'> <RequireHealthOverlay require='node'>
<div className='center-md'> <div className='center-md'>
{!importingFromSigner && jsonCard} {!importingFromSigner && jsonCard}
<br /> {spacer}
{signerCard} {signerCard}
<br /> {spacer}
{!importingFromSigner && phraseCard} {!importingFromSigner && phraseCard}
<br />
<p>{error}</p> <p>{error}</p>
<nav className='form-nav -space-around'> <nav className='form-nav -space-around'>
{currentStep > 1 && ( {currentStep > 1 && (
......
...@@ -63,7 +63,7 @@ class CreateAccount extends Component { ...@@ -63,7 +63,7 @@ class CreateAccount extends Component {
const Steps = this.getSteps(isImport); const Steps = this.getSteps(isImport);
return ( return (
<div> <React.Fragment>
<Header <Header
left={ left={
// Show back button if we already have some accounts, so we can go back to AccountsList // Show back button if we already have some accounts, so we can go back to AccountsList
...@@ -98,17 +98,7 @@ class CreateAccount extends Component { ...@@ -98,17 +98,7 @@ class CreateAccount extends Component {
</div> </div>
) : ( ) : (
<div className='footer-nav_option'> <div className='footer-nav_option'>
{isImport ? ( {isImport ? null : (
<p>
Need to create an account?
<button
className='button -footer'
onClick={this.handleToggleCreateImport}
>
New account
</button>
</p>
) : (
<p> <p>
Already have an account? Already have an account?
<button <button
...@@ -122,7 +112,7 @@ class CreateAccount extends Component { ...@@ -122,7 +112,7 @@ class CreateAccount extends Component {
</div> </div>
)} )}
</nav> </nav>
</div> </React.Fragment>
); );
} }
} }
......
...@@ -13,7 +13,9 @@ import { ...@@ -13,7 +13,9 @@ import {
} from 'react-router-dom'; } from 'react-router-dom';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import isElectron from 'is-electron'; import isElectron from 'is-electron';
import ReactResizeDetector from 'react-resize-detector'; import { Modal } from 'fether-ui';
import semver from 'semver';
import { version } from '../../package.json';
import Accounts from '../Accounts'; import Accounts from '../Accounts';
import BackupAccount from '../BackupAccount'; import BackupAccount from '../BackupAccount';
...@@ -23,29 +25,71 @@ import Send from '../Send'; ...@@ -23,29 +25,71 @@ import Send from '../Send';
import Tokens from '../Tokens'; import Tokens from '../Tokens';
import Whitelist from '../Whitelist'; import Whitelist from '../Whitelist';
const currentVersion = version;
// Use MemoryRouter for production viewing in file:// protocol // Use MemoryRouter for production viewing in file:// protocol
// https://github.com/facebook/create-react-app/issues/3591 // https://github.com/facebook/create-react-app/issues/3591
const Router = const Router =
process.env.NODE_ENV === 'production' ? MemoryRouter : BrowserRouter; process.env.NODE_ENV === 'production' ? MemoryRouter : BrowserRouter;
const electron = isElectron() ? window.require('electron') : null; const electron = isElectron() ? window.require('electron') : null;
@inject('onboardingStore', 'parityStore') @inject('onboardingStore', 'parityStore')
@observer @observer
class App extends Component { class App extends Component {
state = {
newRelease: false // false | {name, url, ignore}
};
componentDidMount () { componentDidMount () {
window.addEventListener('contextmenu', this.handleRightClick); window.addEventListener('contextmenu', this.handleRightClick);
window
.fetch('https://api.github.com/repos/paritytech/fether/releases/latest')
.then(j => j.json())
.then(({ name, html_url: url, tag_name: tag }) => {
const latestVersion = tag.match(/v(\d+\.\d+(\.\d+)?)/)[1];
if (semver.gt(latestVersion, currentVersion)) {
this.setState({
newRelease: {
name,
url,
ignore: false
}
});
}
})
.catch(e => {
console.error('Error while checking for a new version of Fether:', e);
});
} }
componentDidUnmount () { componentDidUnmount () {
window.removeEventListener('contextmenu', this.handleRightClick); window.removeEventListener('contextmenu', this.handleRightClick);
} }
handleResize = (_, height) => { renderModalLinks = () => {
if (!electron) { return (
return; <nav className='form-nav -binary'>
} <button className='button -back' onClick={this.hideNewReleaseModal}>
// Send height to main process Remind me later
electron.ipcRenderer.send('asynchronous-message', 'app-resize', height); </button>
<button className='button' onClick={this.openNewReleaseUrl}>
Download
</button>
</nav>
);
};
hideNewReleaseModal = () => {
this.setState({
newRelease: { ...this.state.newRelease, ignore: true }
});
};
openNewReleaseUrl = () => {
window.open(this.state.newRelease.url, '_blank', 'noopener noreferrer');
}; };
handleRightClick = () => { handleRightClick = () => {
...@@ -64,6 +108,8 @@ class App extends Component { ...@@ -64,6 +108,8 @@ class App extends Component {
parityStore: { api } parityStore: { api }
} = this.props; } = this.props;
const { newRelease } = this.state;
if (isFirstRun) { if (isFirstRun) {
return ( return (
<div className='window'> <div className='window'>
...@@ -79,21 +125,24 @@ class App extends Component { ...@@ -79,21 +125,24 @@ class App extends Component {
// the children, just a <RequireHealthOverlay />. // the children, just a <RequireHealthOverlay />.
if (!api) { if (!api) {
return ( return (
<ReactResizeDetector handleHeight onResize={this.handleResize}> <RequireHealthOverlay fullscreen require='node'>
<RequireHealthOverlay fullscreen require='node'> {/* Adding these components to have minimum height on window */}
{/* Adding these components to have minimum height on window */} <div className='content'>
<div className='content'> <div className='window' />
<div className='window' /> </div>
</div> </RequireHealthOverlay>
</RequireHealthOverlay>
</ReactResizeDetector>
); );
} }
return ( return (
<ReactResizeDetector handleHeight onResize={this.handleResize}> <div className='content'>
<div className='content'> <div className='window'>
<div className='window'> <Modal
title='New version available'
description={newRelease ? `${newRelease.name} was released!` : ''}
visible={newRelease && !newRelease.ignore}
buttons={this.renderModalLinks()}
>
<Router> <Router>
<Switch> <Switch>
{/* The next line is the homepage */} {/* The next line is the homepage */}
...@@ -116,9 +165,9 @@ class App extends Component { ...@@ -116,9 +165,9 @@ class App extends Component {
<Redirect from='*' to='/' /> <Redirect from='*' to='/' />
</Switch> </Switch>
</Router> </Router>
</div> </Modal>
</div> </div>
</ReactResizeDetector> </div>
); );
} }
} }
......
...@@ -49,11 +49,11 @@ class Onboarding extends Component { ...@@ -49,11 +49,11 @@ class Onboarding extends Component {
render () { render () {
return ( return (
<div> <React.Fragment>
<Header title={<h1>Terms of Use</h1>} /> <Header title={<h1>Terms of Use</h1>} />
<div className='window_content'> <div className='window_content'>
<div className='box -padded-extra'> <div className='box -padded -scroller'>
<div className='terms-and-conditions-wrapper'> <div className='terms-and-conditions-wrapper'>
<FetherForm.Field <FetherForm.Field
as={ReactMarkdown} as={ReactMarkdown}
...@@ -76,7 +76,7 @@ class Onboarding extends Component { ...@@ -76,7 +76,7 @@ class Onboarding extends Component {
</button> </button>
</div> </div>
</nav> </nav>
</div> </React.Fragment>
); );
} }
} }
......
...@@ -41,7 +41,7 @@ class HealthModal extends Component { ...@@ -41,7 +41,7 @@ class HealthModal extends Component {
<Modal <Modal
description={this.renderDescription()} description={this.renderDescription()}
fullscreen={fullscreen} fullscreen={fullscreen}
loading={loading} icon={loading}
title={this.renderTitle()} title={this.renderTitle()}
visible={visible} visible={visible}
> >
......