diff --git a/app/app.global.scss b/app/app.global.scss index 4efff7166..30d853820 100644 --- a/app/app.global.scss +++ b/app/app.global.scss @@ -8,6 +8,10 @@ body { background-color: $background-dark; } +* { + overflow: hidden; +} + ul { margin: 0; padding-left: 20px; @@ -51,4 +55,4 @@ ul { .capitalize { text-transform: capitalize; -} \ No newline at end of file +} diff --git a/app/components/Console.js b/app/components/Console.js index d9c90875d..6de0cbef4 100644 --- a/app/components/Console.js +++ b/app/components/Console.js @@ -12,6 +12,7 @@ import DismissibleMessage from './common/DismissibleMessage'; import styles from './Console.scss'; import SpacedGroup from './common/SpacedGroup'; import ActionInput from './common/ActionInput'; +import Scroller from './common/Scroller'; const { dialog } = require('electron').remote; @@ -32,6 +33,7 @@ export default class Console extends Component { history: PropTypes.object.isRequired, store: PropTypes.object.isRequired, errors: PropTypes.object.isRequired, + topNotifOffset: PropTypes.number.isRequired, }; state = { @@ -290,7 +292,8 @@ export default class Console extends Component { - )}; + ) + }; renderConnectButton = connection => { const status = connection.connectionStatus; @@ -358,7 +361,7 @@ export default class Console extends Component { ); } - + renderDeleteButton = connection => { const status = connection.connectionStatus; const isConnected = status === ConnectionStatus.CONNECTED; @@ -555,110 +558,114 @@ export default class Console extends Component { const validation = _.get(this.state, ['formData', 'validation']) || {}; const panes = [ - { menuItem: "Basic", pane: ( - - - - -
- Not recommended unless on wired LAN connection.  - Real-time mode will attempt to prevent delay from accumulating when mirroring. Using it - when on a connection with inconsistent latency will cause extremely choppy playback. -
- + -
)}, - { menuItem: "Advanced", pane: ( - - -
- Only modify if you know what you doing.  - These settings let you select an OBS source (e.g. your dolphin capture) - to be shown if the game is active and hidden if the game is inactive. - You must install the   - OBS Websocket Plugin  - for this feature to work. + + + +
+ Not recommended unless on wired LAN connection.  + Real-time mode will attempt to prevent delay from accumulating when mirroring. Using it + when on a connection with inconsistent latency will cause extremely choppy playback.
- - - - - - - - - - - - - - -
- The relay allows external programs (e.g. stream layouts) to tap into the raw Slippi data stream without affecting mirroring. - This connection's relay port will be shown on the console card after you have saved and is activated once you select connect. -
- +
), + }, + { + menuItem: "Advanced", pane: ( + + +
+ Only modify if you know what you doing.  + These settings let you select an OBS source (e.g. your dolphin capture) + to be shown if the game is active and hidden if the game is inactive. + You must install the   + OBS Websocket Plugin  + for this feature to work. +
+ + -
- - - - - - -
- The connection port should only be changed if you are connecting to a relay, 666 is the port all Wiis use to send data. -
+
+ - - -
- - )}, + + + + + + + + + +
+ The relay allows external programs (e.g. stream layouts) to tap into the raw Slippi data stream without affecting mirroring. + This connection's relay port will be shown on the console card after you have saved and is activated once you select connect. +
+ +
+
+
+ + + + +
+ The connection port should only be changed if you are connecting to a relay, 666 is the port all Wiis use to send data. +
+ +
+
+
+ + ), + }, ]; let errorMessage = null; @@ -685,8 +692,10 @@ export default class Console extends Component { text="Console" history={this.props.history} /> - {this.renderContent()} - {this.renderEditModal()} + + {this.renderContent()} + {this.renderEditModal()} +
); diff --git a/app/components/FileLoader.js b/app/components/FileLoader.js index 221b179d1..6381106dd 100644 --- a/app/components/FileLoader.js +++ b/app/components/FileLoader.js @@ -18,6 +18,7 @@ import DismissibleMessage from './common/DismissibleMessage'; import PageHeader from './common/PageHeader'; import FolderBrowser from './common/FolderBrowser'; import PageWrapper from './PageWrapper'; +import Scroller from './common/Scroller'; export default class FileLoader extends Component { static propTypes = { @@ -37,7 +38,7 @@ export default class FileLoader extends Component { history: PropTypes.object.isRequired, store: PropTypes.object.isRequired, errors: PropTypes.object.isRequired, - globalNotifs: PropTypes.object.isRequired, + topNotifOffset: PropTypes.number.isRequired, }; componentDidMount() { @@ -73,9 +74,8 @@ export default class FileLoader extends Component { // Have to offset both the height and sticky position of the sidebar when a global notif is // active. Wish I knew a better way to do this. - const globalNotifHeightPx = _.get(this.props.globalNotifs, ['activeNotif', 'heightPx']) || 0; const customStyling = { - height: `calc(100vh - ${globalNotifHeightPx}px)`, + height: `calc(100vh - ${this.props.topNotifOffset}px)`, }; // We return a div that will serve as a placeholder for our column as well as a fixed @@ -242,7 +242,6 @@ export default class FileLoader extends Component { renderLoadingState() { const store = this.props.store || {}; - return ( - {this.renderGlobalError()} - {this.renderFilteredFilesNotif(processedFiles)} - {this.renderFileSelection(processedFiles)} + + {this.renderGlobalError()} + {this.renderFilteredFilesNotif(processedFiles)} + {this.renderFileSelection(processedFiles)} + ); } diff --git a/app/components/FileLoader.scss b/app/components/FileLoader.scss index 391b1c494..dd28f5a67 100644 --- a/app/components/FileLoader.scss +++ b/app/components/FileLoader.scss @@ -99,4 +99,4 @@ .bound-link { display: contents; -} +} \ No newline at end of file diff --git a/app/components/GlobalAlert.scss b/app/components/GlobalAlert.scss index 5df92ffb4..abca66708 100644 --- a/app/components/GlobalAlert.scss +++ b/app/components/GlobalAlert.scss @@ -2,7 +2,6 @@ .alert { top: 0px; - position: fixed !important; width: 100% !important; z-index: 1000; margin: 0 !important; @@ -31,4 +30,4 @@ margin-left: 6px; cursor: pointer; font-weight: bold; -} +} \ No newline at end of file diff --git a/app/components/PageWrapper.js b/app/components/PageWrapper.js index 7baa74cb3..30574c523 100644 --- a/app/components/PageWrapper.js +++ b/app/components/PageWrapper.js @@ -1,5 +1,4 @@ import React, { Component } from 'react'; -import _ from 'lodash'; import log from 'electron-log'; import PropTypes from 'prop-types'; import { ipcRenderer } from 'electron'; @@ -17,9 +16,8 @@ class PageWrapper extends Component { static propTypes = { children: PropTypes.any.isRequired, history: PropTypes.object.isRequired, - + // From redux - store: PropTypes.object.isRequired, appUpgradeDownloaded: PropTypes.func.isRequired, gameProfileLoad: PropTypes.func.isRequired, playFile: PropTypes.func.isRequired, @@ -39,7 +37,7 @@ class PageWrapper extends Component { // When main process (main.dev.js) tells us an update has been downloaded, trigger // a global notif to be shown this.props.appUpgradeDownloaded(upgradeDetails); - } + }; onPlayReplay = (event, slpPath) => { log.info(`playing file ${slpPath}`); @@ -48,27 +46,12 @@ class PageWrapper extends Component { this.props.playFile({ fullPath: slpPath, }); - } + }; render() { - let spacerEl = null; - - const notifHeightPx = _.get(this.props.store, ['activeNotif', 'heightPx']); - if (notifHeightPx) { - const customStyling = { - height: `${notifHeightPx}px`, - }; - - // User spacer element to give space for notif. I tried using padding on the top-level div - // and that sorta worked but it didn't seem to respond well when I closed the notif while - // on the file loader page, there would still be space above the file selector - spacerEl =
; - } - return ( - {spacerEl}
{this.props.children}
); @@ -82,11 +65,14 @@ function mapStateToProps(state) { } function mapDispatchToProps(dispatch) { - return bindActionCreators({ - ...NotifActions, - ...GameActions, - playFile: playFile, - }, dispatch); + return bindActionCreators( + { + ...NotifActions, + ...GameActions, + playFile: playFile, + }, + dispatch + ); } export default connect( diff --git a/app/components/Settings.js b/app/components/Settings.js index 7c829bcbb..88e7efdfc 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -16,6 +16,7 @@ import DismissibleMessage from './common/DismissibleMessage'; import styles from './Settings.scss'; import PageWrapper from './PageWrapper'; import SpacedGroup from './common/SpacedGroup'; +import Scroller from './common/Scroller'; const { app } = require('electron').remote; @@ -34,6 +35,7 @@ export default class Settings extends Component { history: PropTypes.object.isRequired, store: PropTypes.object.isRequired, errors: PropTypes.object.isRequired, + topNotifOffset: PropTypes.number.isRequired, }; componentDidMount() { @@ -322,9 +324,11 @@ export default class Settings extends Component { infoText={`App v${currentVersion}`} history={this.props.history} /> - {this.renderContent()} + + {this.renderContent()} +
); } -} +} \ No newline at end of file diff --git a/app/components/common/Scroller.js b/app/components/common/Scroller.js new file mode 100644 index 000000000..1eaeb8056 --- /dev/null +++ b/app/components/common/Scroller.js @@ -0,0 +1,19 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; + +export default class Scroller extends Component { + static propTypes = { + children: PropTypes.any.isRequired, + topOffset: PropTypes.number.isRequired, + }; + + render() { + const customStyles = { + overflowY: 'auto', + height: `calc(100vh - ${this.props.topOffset + 85}px)`, + width: `calc(100% + 17px)`, + }; + + return
{this.props.children}
; + } +} diff --git a/app/components/stats/GameProfile.js b/app/components/stats/GameProfile.js index 4fa688c7a..7f523ac17 100644 --- a/app/components/stats/GameProfile.js +++ b/app/components/stats/GameProfile.js @@ -5,7 +5,6 @@ import PropTypes from 'prop-types'; import { Header, Segment, - Sticky, Image, Icon, Button, @@ -26,6 +25,7 @@ import getLocalImage from '../../utils/image'; import * as timeUtils from '../../utils/time'; import * as playerUtils from '../../utils/players'; import PageWrapper from '../PageWrapper'; +import Scroller from '../common/Scroller'; export default class GameProfile extends Component { static propTypes = { @@ -40,11 +40,7 @@ export default class GameProfile extends Component { // store data store: PropTypes.object.isRequired, errors: PropTypes.object.isRequired, - globalNotifs: PropTypes.object.isRequired, - }; - - state = { - isStatsStuck: false, + topNotifOffset: PropTypes.number.isRequired, }; refStats = null; @@ -79,7 +75,7 @@ export default class GameProfile extends Component { renderLoading() { const store = this.props.store || {}; - + return ( ( @@ -232,49 +232,20 @@ export default class GameProfile extends Component { } renderStats() { - const handleStick = () => { - this.setState({ - isStatsStuck: true, - }); - }; - - const handleUnstick = () => { - this.setState({ - isStatsStuck: false, - }); - }; - - const statsSectionClasses = classNames( - { - [styles['stuck']]: this.state.isStatsStuck, - }, - styles['stats-section'] - ); - const globalNotifHeightPx = - _.get(this.props.globalNotifs, ['activeNotif', 'heightPx']) || 0; + const scrollerOffset = this.props.topNotifOffset + 120; // + 120 to account for game-specific header return ( - - {this.renderErrorModal()} - -
- {this.renderMatchupDisplay()} - {this.renderGameDetails()} + + + {this.renderErrorModal()} +
+ {this.renderOverall()} + {this.renderStocks()} + {this.renderPunishes()}
- -
- {this.renderOverall()} - {this.renderStocks()} - {this.renderPunishes()} -
-
+ +
); } @@ -401,6 +372,10 @@ export default class GameProfile extends Component {
+
+ {this.renderMatchupDisplay()} + {this.renderGameDetails()} +
{this.renderContent()}
diff --git a/app/components/stats/GameProfile.scss b/app/components/stats/GameProfile.scss index 4acc758cb..7a8020ff9 100644 --- a/app/components/stats/GameProfile.scss +++ b/app/components/stats/GameProfile.scss @@ -1,12 +1,15 @@ -@import "../../colors.global"; +@import '../../colors.global'; $header-height: 97px; .stats-player-header { + position: relative; background: $background-lightest !important; - box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - margin: 0 -34px 0 -34px !important; - padding: 0 48px 0 48px !important; + width: calc(100% + 40px); + padding: 0 40px 0 34px; + margin-left: -20px; + z-index: 2; // needed for shadow to show up + box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2); .matchup-display { display: grid; @@ -39,7 +42,6 @@ $header-height: 97px; .play-button { justify-self: end; - margin-right: 14px; } } @@ -79,19 +81,6 @@ $header-height: 97px; } } -.sticky-names { - z-index: 2; - position: relative; -} - -.stats-section { - padding-top: 28px; - - &.stuck { - margin-top: $header-height !important; - } -} - .vs-element { color: rgba(255, 255, 255, 0.5); line-height: 0.8; diff --git a/app/containers/ConsolePage.js b/app/containers/ConsolePage.js index 281988e00..51915a57a 100644 --- a/app/containers/ConsolePage.js +++ b/app/containers/ConsolePage.js @@ -9,6 +9,7 @@ function mapStateToProps(state) { return { store: state.console, errors: state.errors, + topNotifOffset: _.get(state.notifs, ['activeNotif', 'heightPx']) || 0, }; } diff --git a/app/containers/FileLoaderPage.js b/app/containers/FileLoaderPage.js index 64071b2aa..c271db301 100644 --- a/app/containers/FileLoaderPage.js +++ b/app/containers/FileLoaderPage.js @@ -10,7 +10,7 @@ function mapStateToProps(state) { return { store: state.fileLoader, errors: state.errors, - globalNotifs: state.notifs, + topNotifOffset: _.get(state.notifs, ['activeNotif', 'heightPx']) || 0, }; } diff --git a/app/containers/GameProfilePage.js b/app/containers/GameProfilePage.js index 008a11ca1..6cd3c3f67 100644 --- a/app/containers/GameProfilePage.js +++ b/app/containers/GameProfilePage.js @@ -1,3 +1,4 @@ +import _ from "lodash"; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import GameProfile from '../components/stats/GameProfile'; @@ -8,7 +9,7 @@ function mapStateToProps(state) { return { store: state.game, errors: state.errors, - globalNotifs: state.notifs, + topNotifOffset: _.get(state.notifs, ['activeNotif', 'heightPx']) || 0, }; } diff --git a/app/containers/SettingsPage.js b/app/containers/SettingsPage.js index cf5af9a66..fb8bec8a5 100644 --- a/app/containers/SettingsPage.js +++ b/app/containers/SettingsPage.js @@ -9,6 +9,7 @@ function mapStateToProps(state) { return { store: state.settings, errors: state.errors, + topNotifOffset: _.get(state.notifs, ['activeNotif', 'heightPx']) || 0, }; }