diff --git a/src/Wrapper.js b/src/Wrapper.js index 9ec0d47aa..6afda83e5 100644 --- a/src/Wrapper.js +++ b/src/Wrapper.js @@ -1,6 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' import styled from 'styled-components' +import { Gesture } from 'react-with-gesture' import { Viewport } from '@aragon/ui' import { Apps, Permissions, Settings } from './apps' import AppIFrame from './components/App/AppIFrame' @@ -22,6 +23,10 @@ import { APPS_STATUS_LOADING } from './symbols' import { addressesEqual } from './web3-utils' import ethereumLoadingAnimation from './assets/ethereum-loading.svg' +const THRESHOLD_DISTANCE = 10 +const THRESHOLD_DIRECTION = 0.2 +const THRESHOLD_PROGRESS = 0.5 + class Wrapper extends React.PureComponent { static propTypes = { account: EthereumAddressType, @@ -42,10 +47,12 @@ class Wrapper extends React.PureComponent { onRequestEnable: PropTypes.func.isRequired, permissionsLoading: PropTypes.bool.isRequired, autoClosingPanel: PropTypes.bool.isRequired, + swipeEnabled: PropTypes.bool.isRequired, transactionBag: PropTypes.object, walletNetwork: PropTypes.string, walletProviderId: PropTypes.string, walletWeb3: PropTypes.object, + width: PropTypes.number.isRequired, wrapper: PropTypes.object, } @@ -115,6 +122,9 @@ class Wrapper extends React.PureComponent { this.setState({ menuPanelOpened: Boolean(value) }) } } + handleMenuPanelOpen = () => { + this.setState({ menuPanelOpened: true }) + } handleMenuPanelClose = () => { this.setState({ menuPanelOpened: false }) } @@ -159,41 +169,53 @@ class Wrapper extends React.PureComponent { locator, onRequestAppsReload, onRequestEnable, + swipeEnabled, transactionBag, walletNetwork, walletProviderId, walletWeb3, + width, } = this.props const { menuPanelOpened, notifications, notificationOpen } = this.state return (
{banner} - - app.hasWebApp)} - appsStatus={appsStatus} - activeInstanceId={locator.instanceId} - connected={connected} - notifications={notifications.length} - daoAddress={daoAddress} - opened={menuPanelOpened} - autoClosing={autoClosingPanel} - onOpenApp={this.openApp} - onCloseMenuPanel={this.handleMenuPanelClose} - onRequestAppsReload={onRequestAppsReload} - onNotificationClicked={this.handleNotificationClicked} - notificationOpen={notificationOpen} - /> - - - {this.renderApp(locator.instanceId, locator.params)} - - + + {progress => ( + + app.hasWebApp)} + appsStatus={appsStatus} + activeInstanceId={locator.instanceId} + connected={connected} + notifications={notifications.length} + daoAddress={daoAddress} + openProgress={progress} + autoClosing={autoClosingPanel} + onOpenApp={this.openApp} + onCloseMenuPanel={this.handleMenuPanelClose} + onRequestAppsReload={onRequestAppsReload} + onNotificationClicked={this.handleNotificationClicked} + notificationOpen={notificationOpen} + /> + + + {this.renderApp(locator.instanceId, locator.params)} + + + )} + { + let _progress = 0 + + const SwipeContainer = ({ + children, + enabled, + menuPanelOpened, + onMenuPanelClose, + onMenuPanelOpen, + width, + }) => { + const oneThirdWindowWidth = width / 3 + + if (!enabled) { + return {children(Number(menuPanelOpened))} + } + + return ( + + {({ + delta: [xDelta, yDelta], + direction: [xDir, yDir], + down, + event, + initial: [xInitial], + xy: [x], + }) => { + if (!down && _progress > 0 && _progress < 1) { + _progress = !menuPanelOpened + ? _progress > THRESHOLD_PROGRESS + ? 1 + : 0 + : _progress < THRESHOLD_PROGRESS + ? 0 + : 1 + if (_progress === 1) { + setTimeout(() => { + _progress = 0 + onMenuPanelOpen() + }, 1) + } + if (_progress === 0) { + setTimeout(() => { + onMenuPanelClose() + }, 1) + } + return {children(_progress)} + } + + let progress = _progress || Number(menuPanelOpened) + + if ( + (progress > 0 && progress < 1) || + (down && + xDelta && + yDelta > -THRESHOLD_DISTANCE && + yDelta < THRESHOLD_DISTANCE && + xDir && + yDir > -THRESHOLD_DIRECTION && + yDir < THRESHOLD_DIRECTION) + ) { + event.preventDefault() + if ( + xDelta > 0 && + !menuPanelOpened && + xInitial < oneThirdWindowWidth + ) { + // opening + progress = _progress = Math.max(0, Math.min(1, x / width)) + } else if (menuPanelOpened) { + // closing + progress = _progress = Math.max( + 0, + Math.min(1, 1 + xDelta / width) + ) + } + } + + return {children(progress)} + }} + + ) + } + + SwipeContainer.propTypes = { + children: PropTypes.func.isRequired, + enabled: PropTypes.bool.isRequired, + menuPanelOpened: PropTypes.bool.isRequired, + onMenuPanelClose: PropTypes.func.isRequired, + onMenuPanelOpen: PropTypes.func.isRequired, + width: PropTypes.number.isRequired, + } + + return SwipeContainer +})() + const Main = styled.div` display: flex; flex-direction: column; @@ -364,6 +482,13 @@ const LoadingApps = () => ( export default props => ( - {({ below }) => } + {({ below, width }) => ( + + )} )