From a2288fb8751e004f8d3477bca2e264c02e17415b Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Wed, 9 Sep 2020 17:00:28 -0700 Subject: [PATCH 01/87] add broadcast page and main menu button --- app/components/Broadcast.js | 84 ++++++++++++++++++++++++++ app/components/Broadcast.scss | 101 ++++++++++++++++++++++++++++++++ app/components/Home.js | 10 ++++ app/containers/BroadcastPage.js | 19 ++++++ app/routes.js | 2 + 5 files changed, 216 insertions(+) create mode 100644 app/components/Broadcast.js create mode 100644 app/components/Broadcast.scss create mode 100644 app/containers/BroadcastPage.js diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js new file mode 100644 index 000000000..26f755d64 --- /dev/null +++ b/app/components/Broadcast.js @@ -0,0 +1,84 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; + +import { + Button, +} from 'semantic-ui-react'; + +import PageHeader from './common/PageHeader'; +import PageWrapper from './PageWrapper'; +import DismissibleMessage from './common/DismissibleMessage'; + +import styles from './Broadcast.scss'; +import Scroller from './common/Scroller'; + +export default class Broadcast extends Component { + static propTypes = { + // error actions + dismissError: PropTypes.func.isRequired, + + // store data + history: PropTypes.object.isRequired, + // store: PropTypes.object.isRequired, + errors: PropTypes.object.isRequired, + topNotifOffset: PropTypes.number.isRequired, + }; + + renderGlobalError() { + const errors = this.props.errors || {}; + const errorKey = 'broadcast-global'; + + const showGlobalError = errors.displayFlags[errorKey] || false; + const globalErrorMessage = errors.messages[errorKey] || ''; + return ( + + ); + } + + renderButton() { + return ( + + ); + } + + renderContent() { + return ( +
+ {this.renderGlobalError()} + {this.renderButton()} +
+ ); + } + + render() { + return ( + +
+ + + {this.renderContent()} + +
+
+ ); + } +} diff --git a/app/components/Broadcast.scss b/app/components/Broadcast.scss new file mode 100644 index 000000000..eb631bade --- /dev/null +++ b/app/components/Broadcast.scss @@ -0,0 +1,101 @@ +@import "../colors.global.scss"; + +.container { + max-width: 700px !important; + margin-left: auto; + margin-right: auto; +} + +.section { + margin-bottom: 48px; +} + +.global-action-section { + margin-bottom: 15px; +} + +.card { + box-shadow: 3px 3px 2px rgba(0, 0, 0, 0.1) !important; + background: none !important; + border-style: solid !important; + border-width: 1px !important; + border-color: $background-darkest !important; + color: $foreground; + margin: 0 !important; + + .content { + border-color: $background-darkest !important; + background-color: $background-light !important; + } + + .warning-bar { + border-color: $background-darkest !important; + background-color: $primary-yellow !important; + padding-top: 4px !important; + padding-bottom: 5px !important; + color: black; + font-weight: 700; + } +} + +.label { + font-weight: bold; + color: rgba(255, 255, 255, 0.5); + margin-right: 4px; +} + +.conn-content-grid { + display: grid; + grid-template-columns: auto 1fr; + grid-column-gap: 6px; +} + +.conn-button-grid { + display: grid; + grid-template-columns: auto auto 1fr auto auto; + grid-column-gap: 3px; +} + +.conn-status-value { + font-weight: bold; + + &.gray { + color: gray; + } + + &.green { + color: $primary-green; + } + + &.yellow { + color: $primary-yellow; + } + + &.white { + color: white; + } +} + +.description { + color: gray; + // Move label margin to be under the description + margin-top: -4px; + margin-bottom: 4px; +} + +.empty-state-header { + color: rgba(255, 255, 255, 0.6) !important; + display: inline-block; + + :global(.sub) { + color: rgba(255, 255, 255, 0.5) !important; + } +} + +.connect-btn { + width: 133px; +} + +.spacer { + padding: 10px; +} \ No newline at end of file diff --git a/app/components/Home.js b/app/components/Home.js index 3b4820b2d..7560e3a89 100644 --- a/app/components/Home.js +++ b/app/components/Home.js @@ -130,6 +130,16 @@ export default class Home extends Component { ) ); + navigationElements.push( + this.generateNav( + 'podcast', + 'Broadcast Gameplay', + 'Allow others to spectate your gameplay', + '/broadcast', + false + ) + ); + navigationElements.push( this.generateNav( 'setting', diff --git a/app/containers/BroadcastPage.js b/app/containers/BroadcastPage.js new file mode 100644 index 000000000..8175eca4e --- /dev/null +++ b/app/containers/BroadcastPage.js @@ -0,0 +1,19 @@ +import _ from 'lodash'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import Broadcast from '../components/Broadcast'; +import * as ErrorActions from '../actions/error'; + +function mapStateToProps(state) { + return { + errors: state.errors, + topNotifOffset: _.get(state.notifs, ['activeNotif', 'heightPx']) || 0, + }; +} + +function mapDispatchToProps(dispatch) { + const allActions = _.extend({}, ErrorActions); + return bindActionCreators(allActions, dispatch); +} + +export default connect(mapStateToProps, mapDispatchToProps)(Broadcast); diff --git a/app/routes.js b/app/routes.js index 8d1f76ff9..687a1339a 100644 --- a/app/routes.js +++ b/app/routes.js @@ -6,6 +6,7 @@ import FileLoaderPage from './containers/FileLoaderPage'; import GameProfilePage from './containers/GameProfilePage'; import SettingsPage from './containers/SettingsPage'; import ConsolePage from './containers/ConsolePage'; +import BroadcastPage from './containers/BroadcastPage'; export default () => ( @@ -13,6 +14,7 @@ export default () => ( + From f14ccf1ecffe18c71ed83af637047dd22d0c0027 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Thu, 10 Sep 2020 17:12:57 +1000 Subject: [PATCH 02/87] Add broadcast actions --- app/actions/broadcast.js | 16 ++++++++++++++++ app/components/Broadcast.js | 23 +++++++++++++++++++--- app/containers/BroadcastPage.js | 4 +++- app/reducers/broadcast.js | 34 +++++++++++++++++++++++++++++++++ app/reducers/index.js | 2 ++ 5 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 app/actions/broadcast.js create mode 100644 app/reducers/broadcast.js diff --git a/app/actions/broadcast.js b/app/actions/broadcast.js new file mode 100644 index 000000000..9ee96e536 --- /dev/null +++ b/app/actions/broadcast.js @@ -0,0 +1,16 @@ +export const START_BROADCAST = 'START_BROADCAST'; +export const STOP_BROADCAST = 'STOP_BROADCAST'; + +export function startBroadcast() { + console.log("starting broadcast..."); + return { + type: START_BROADCAST, + }; +} + +export function stopBroadcast() { + console.log("stopping broadcast..."); + return { + type: STOP_BROADCAST, + }; +} diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 26f755d64..856174444 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -16,10 +16,13 @@ export default class Broadcast extends Component { static propTypes = { // error actions dismissError: PropTypes.func.isRequired, + // broadcast actions + startBroadcast: PropTypes.func.isRequired, + stopBroadcast: PropTypes.func.isRequired, // store data history: PropTypes.object.isRequired, - // store: PropTypes.object.isRequired, + broadcast: PropTypes.object.isRequired, errors: PropTypes.object.isRequired, topNotifOffset: PropTypes.number.isRequired, }; @@ -45,22 +48,36 @@ export default class Broadcast extends Component { } renderButton() { + const { isBroadcasting } = this.props.broadcast; + const buttonText = isBroadcasting ? "Stop Broadcast" : "Start Broadcast"; + const onClick = () => { + if (isBroadcasting) { + this.props.stopBroadcast(); + } else { + this.props.startBroadcast(); + } + } return ( ); } renderContent() { + const { startTime, endTime, isBroadcasting } = this.props.broadcast; + console.log(JSON.stringify(this.props)); return (
{this.renderGlobalError()} {this.renderButton()} +
start: {JSON.stringify(startTime)}
+
end: {JSON.stringify(endTime)}
+
isbroadcasting: {JSON.stringify(isBroadcasting)}
); } diff --git a/app/containers/BroadcastPage.js b/app/containers/BroadcastPage.js index 8175eca4e..e0b742bae 100644 --- a/app/containers/BroadcastPage.js +++ b/app/containers/BroadcastPage.js @@ -3,16 +3,18 @@ import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import Broadcast from '../components/Broadcast'; import * as ErrorActions from '../actions/error'; +import * as BroadcastActions from '../actions/broadcast'; function mapStateToProps(state) { return { errors: state.errors, + broadcast: state.broadcast, topNotifOffset: _.get(state.notifs, ['activeNotif', 'heightPx']) || 0, }; } function mapDispatchToProps(dispatch) { - const allActions = _.extend({}, ErrorActions); + const allActions = _.extend({}, ErrorActions, BroadcastActions); return bindActionCreators(allActions, dispatch); } diff --git a/app/reducers/broadcast.js b/app/reducers/broadcast.js new file mode 100644 index 000000000..4ee5e8af3 --- /dev/null +++ b/app/reducers/broadcast.js @@ -0,0 +1,34 @@ +import { START_BROADCAST, STOP_BROADCAST } from '../actions/broadcast'; + +// Default state for this reducer +const defaultState = { + startTime: null, + endTime: null, + isBroadcasting: false, +}; + +export default function broadcastReducer(state = defaultState, action) { + switch (action.type) { + case START_BROADCAST: + return startBroadcast(state, action); + case STOP_BROADCAST: + return stopBroadcast(state, action); + default: + return state; + } +} + +function startBroadcast(state) { + const newState = { ...state }; + newState.startTime = new Date(); + newState.endTime = null; + newState.isBroadcasting = true; + return newState; +} + +function stopBroadcast(state) { + const newState = { ...state }; + newState.endTime = new Date(); + newState.isBroadcasting = false; + return newState; +} diff --git a/app/reducers/index.js b/app/reducers/index.js index 1deb22c9b..e4959420e 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -7,6 +7,7 @@ import console from './console'; import game from './game'; import errors from './error'; import notifs from './notifs'; +import broadcast from './broadcast'; export default function createRootReducer(history) { return combineReducers({ @@ -17,5 +18,6 @@ export default function createRootReducer(history) { game: game, errors: errors, notifs: notifs, + broadcast: broadcast, }); } From dacb76598fac55767c028c3ee916360510f1253a Mon Sep 17 00:00:00 2001 From: Vince Au Date: Fri, 11 Sep 2020 12:00:47 +1000 Subject: [PATCH 03/87] Add BroadcastManager for handling Dolphin and Slippi connections --- app/actions/broadcast.js | 28 ++++++--- app/components/Broadcast.js | 4 +- app/domain/BroadcastManager.js | 112 +++++++++++++++++++++++++++++++++ app/domain/SlpNetworking.js | 6 +- app/reducers/broadcast.js | 27 +++++++- 5 files changed, 162 insertions(+), 15 deletions(-) create mode 100644 app/domain/BroadcastManager.js diff --git a/app/actions/broadcast.js b/app/actions/broadcast.js index 9ee96e536..16814fd0a 100644 --- a/app/actions/broadcast.js +++ b/app/actions/broadcast.js @@ -1,16 +1,28 @@ +import { BroadcastManager } from '../domain/BroadcastManager'; + export const START_BROADCAST = 'START_BROADCAST'; export const STOP_BROADCAST = 'STOP_BROADCAST'; +export const SET_DOLPHIN_STATUS = 'SET_DOLPHIN_STATUS'; +export const SET_SLIPPI_STATUS = 'SET_SLIPPI_STATUS'; + +const broadcastManager = new BroadcastManager(); export function startBroadcast() { - console.log("starting broadcast..."); - return { - type: START_BROADCAST, - }; + // return async (dispatch, getState) => { + broadcastManager.start(); + + // dispatch({ + // type: START_BROADCAST, + // }) + // } } export function stopBroadcast() { - console.log("stopping broadcast..."); - return { - type: STOP_BROADCAST, - }; + // return async (dispatch, getState) => { + broadcastManager.stop(); + + // dispatch({ + // type: STOP_BROADCAST, + // }) + // } } diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 856174444..2dd633139 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -69,7 +69,7 @@ export default class Broadcast extends Component { } renderContent() { - const { startTime, endTime, isBroadcasting } = this.props.broadcast; + const { slippiConnectionStatus, dolphinConnectionStatus, startTime, endTime, isBroadcasting } = this.props.broadcast; console.log(JSON.stringify(this.props)); return (
@@ -77,6 +77,8 @@ export default class Broadcast extends Component { {this.renderButton()}
start: {JSON.stringify(startTime)}
end: {JSON.stringify(endTime)}
+
dolphin connection status: {JSON.stringify(dolphinConnectionStatus)}
+
slippi connection status: {JSON.stringify(slippiConnectionStatus)}
isbroadcasting: {JSON.stringify(isBroadcasting)}
); diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js new file mode 100644 index 000000000..d84720b23 --- /dev/null +++ b/app/domain/BroadcastManager.js @@ -0,0 +1,112 @@ +/* eslint-disable no-underscore-dangle */ + +import log from 'electron-log'; +import WebSocket from 'ws'; + +import { DolphinConnection, Ports, ConnectionEvent, ConnectionStatus } from '@slippi/slippi-js'; +import { store } from '../index'; +import { SET_DOLPHIN_STATUS, SET_SLIPPI_STATUS } from '../actions/broadcast'; +import { displayError } from '../actions/error'; + +const SLIPPI_SERVER = 'ws://localhost:9898/'; + +/** + * Responsible for retrieving Dolphin game data over enet and sending the data + * to the Slippi server over websockets. + */ +// eslint-disable-next-line import/prefer-default-export +export class BroadcastManager { + constructor() { + this.socket = null; + this.connection = new DolphinConnection(); + this.connection.on(ConnectionEvent.STATUS_CHANGE, status => { + store.dispatch({ + type: SET_DOLPHIN_STATUS, + status: status, + }); + switch(status) { + case ConnectionStatus.CONNECTED: + this._connectToSlippiServer(); + break; + case ConnectionStatus.DISCONNECTED: + this._disconnectFromSlippiServer(); + break; + default: + break; + } + }); + this.connection.on(ConnectionEvent.DATA, (data) => { + this._handleGameData(data); + }); + } + + /** + * Connects to Dolphin and the Slippi server, forwarding data from Dolphin to Slippi + */ + start() { + this.connection.connect( + '127.0.0.1', + Ports.DEFAULT + ); + } + + stop() { + this.connection.disconnect(); + } + + _handleGameData(data) { + if (this.socket) { + this.socket.send(data); + } + } + + _connectToSlippiServer() { + if (this.socket) { + // We're already connected + console.log("skipping websocket connection since we're already connected"); + return; + } + + // Indicate we're connecting to the Slippi server + console.log("Attempting to connect to the Slippi server"); + store.dispatch({ + type: SET_SLIPPI_STATUS, + status: ConnectionStatus.CONNECTING, + }); + + this.socket = new WebSocket(SLIPPI_SERVER); + this.socket.on('open', () => { + store.dispatch({ + type: SET_SLIPPI_STATUS, + status: ConnectionStatus.CONNECTED, + }); + }); + this.socket.on('close', () => { + store.dispatch({ + type: SET_SLIPPI_STATUS, + status: ConnectionStatus.DISCONNECTED, + }); + // Clear the socket + console.log("clearing the socket"); + this.socket = null; + // Disconnect from Dolphin too if we're still connected + this.connection.disconnect(); + }); + this.socket.on('error', (err) => { + log.error("[BroadcastManager] Error connecting to Slippi server: ", err); + const errorAction = displayError( + 'broadcast-global', + err.message, + ); + store.dispatch(errorAction); + }); + } + + _disconnectFromSlippiServer() { + if (this.socket) { + this.socket.close(); + } + } +} + +/* eslint-enable no-underscore-dangle */ \ No newline at end of file diff --git a/app/domain/SlpNetworking.js b/app/domain/SlpNetworking.js index ef35f642f..044e0aae5 100644 --- a/app/domain/SlpNetworking.js +++ b/app/domain/SlpNetworking.js @@ -21,7 +21,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import _ from 'lodash'; -import { ConsoleConnection, ConnectionStatus } from '@slippi/slippi-js'; +import { DolphinConnection, ConnectionStatus } from '@slippi/slippi-js'; import { store } from '../index'; import { connectionStateChanged } from '../actions/console'; @@ -122,8 +122,8 @@ export default class SlpNetworking { this.slpFileWriter.connectOBS(); this.dolphinManager.updateSettings(connectionSettings); - console.log("Connecting"); - if (!this.consoleConn) this.consoleConn = new ConsoleConnection(); + console.log(`Connecting to: ${this.ipAdress}:${this.port}`); + if (!this.consoleConn) this.consoleConn = new DolphinConnection(); this.consoleConn.connect(this.ipAddress, this.port); this.consoleConn.on("handshake", (details) => { console.log(details); diff --git a/app/reducers/broadcast.js b/app/reducers/broadcast.js index 4ee5e8af3..a39926c1d 100644 --- a/app/reducers/broadcast.js +++ b/app/reducers/broadcast.js @@ -1,9 +1,12 @@ -import { START_BROADCAST, STOP_BROADCAST } from '../actions/broadcast'; +import { ConnectionStatus } from '@slippi/slippi-js'; +import { START_BROADCAST, STOP_BROADCAST, SET_DOLPHIN_STATUS, SET_SLIPPI_STATUS } from '../actions/broadcast'; // Default state for this reducer const defaultState = { startTime: null, endTime: null, + dolphinConnectionStatus: ConnectionStatus.DISCONNECTED, + slippiConnectionStatus: ConnectionStatus.DISCONNECTED, isBroadcasting: false, }; @@ -13,22 +16,40 @@ export default function broadcastReducer(state = defaultState, action) { return startBroadcast(state, action); case STOP_BROADCAST: return stopBroadcast(state, action); + case SET_DOLPHIN_STATUS: + return setDolphinStatus(state, action); + case SET_SLIPPI_STATUS: + return setSlippiStatus(state, action); default: return state; } } +function setSlippiStatus(state, action) { + const newState = { ...state }; + const { status } = action; + newState.slippiConnectionStatus = status; + newState.isBroadcasting = newState.slippiConnectionStatus === ConnectionStatus.CONNECTED && newState.dolphinConnectionStatus === ConnectionStatus.CONNECTED; + return newState; +} + +function setDolphinStatus(state, action) { + const newState = { ...state }; + const { status } = action; + newState.dolphinConnectionStatus = status; + newState.isBroadcasting = newState.slippiConnectionStatus === ConnectionStatus.CONNECTED && newState.dolphinConnectionStatus === ConnectionStatus.CONNECTED; + return newState; +} + function startBroadcast(state) { const newState = { ...state }; newState.startTime = new Date(); newState.endTime = null; - newState.isBroadcasting = true; return newState; } function stopBroadcast(state) { const newState = { ...state }; newState.endTime = new Date(); - newState.isBroadcasting = false; return newState; } From acdbaef46bd03bed217a09fba4698ff86e39e17a Mon Sep 17 00:00:00 2001 From: Vince Au Date: Fri, 11 Sep 2020 12:13:01 +1000 Subject: [PATCH 04/87] First connect to Slippi server before connecting to local Dolphin --- app/domain/BroadcastManager.js | 55 ++++++++++++++-------------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index d84720b23..68ba14958 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -24,15 +24,9 @@ export class BroadcastManager { type: SET_DOLPHIN_STATUS, status: status, }); - switch(status) { - case ConnectionStatus.CONNECTED: - this._connectToSlippiServer(); - break; - case ConnectionStatus.DISCONNECTED: - this._disconnectFromSlippiServer(); - break; - default: - break; + // Disconnect from Slippi server when we disconnect from Dolphin + if (status === ConnectionStatus.DISCONNECTED) { + this.stop(); } }); this.connection.on(ConnectionEvent.DATA, (data) => { @@ -41,29 +35,12 @@ export class BroadcastManager { } /** - * Connects to Dolphin and the Slippi server, forwarding data from Dolphin to Slippi + * Connects to the Slippi server and the local Dolphin instance */ start() { - this.connection.connect( - '127.0.0.1', - Ports.DEFAULT - ); - } - - stop() { - this.connection.disconnect(); - } - - _handleGameData(data) { - if (this.socket) { - this.socket.send(data); - } - } - - _connectToSlippiServer() { if (this.socket) { // We're already connected - console.log("skipping websocket connection since we're already connected"); + console.log("Skipping websocket connection since we're already connected"); return; } @@ -75,23 +52,31 @@ export class BroadcastManager { }); this.socket = new WebSocket(SLIPPI_SERVER); + this.socket.on('open', () => { + // We successfully connected to the Slippi server store.dispatch({ type: SET_SLIPPI_STATUS, status: ConnectionStatus.CONNECTED, }); + + // Now try connect to our local Dolphin instance + this.connection.connect( + '127.0.0.1', + Ports.DEFAULT + ); }); + this.socket.on('close', () => { store.dispatch({ type: SET_SLIPPI_STATUS, status: ConnectionStatus.DISCONNECTED, }); - // Clear the socket - console.log("clearing the socket"); + // Clear the socket and disconnect from Dolphin too if we're still connected this.socket = null; - // Disconnect from Dolphin too if we're still connected this.connection.disconnect(); }); + this.socket.on('error', (err) => { log.error("[BroadcastManager] Error connecting to Slippi server: ", err); const errorAction = displayError( @@ -102,11 +87,17 @@ export class BroadcastManager { }); } - _disconnectFromSlippiServer() { + stop() { if (this.socket) { this.socket.close(); } } + + _handleGameData(data) { + if (this.socket) { + this.socket.send(data); + } + } } /* eslint-enable no-underscore-dangle */ \ No newline at end of file From bac546ecf9fdc421e2cc7342e3b55c0bdc947071 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Fri, 11 Sep 2020 12:38:12 +1000 Subject: [PATCH 05/87] Fix action dispatching --- app/actions/broadcast.js | 40 ++++++++++++++++++++-------------- app/domain/BroadcastManager.js | 23 +++++-------------- app/reducers/broadcast.js | 12 +++++----- 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/app/actions/broadcast.js b/app/actions/broadcast.js index 16814fd0a..a5faf90b3 100644 --- a/app/actions/broadcast.js +++ b/app/actions/broadcast.js @@ -1,28 +1,36 @@ import { BroadcastManager } from '../domain/BroadcastManager'; -export const START_BROADCAST = 'START_BROADCAST'; -export const STOP_BROADCAST = 'STOP_BROADCAST'; export const SET_DOLPHIN_STATUS = 'SET_DOLPHIN_STATUS'; export const SET_SLIPPI_STATUS = 'SET_SLIPPI_STATUS'; const broadcastManager = new BroadcastManager(); -export function startBroadcast() { - // return async (dispatch, getState) => { - broadcastManager.start(); +export function setDolphinStatus(status) { + return async (dispatch) => { + dispatch({ + type: SET_DOLPHIN_STATUS, + status: status, + }) + } +} - // dispatch({ - // type: START_BROADCAST, - // }) - // } +export function setSlippiStatus(status) { + return async (dispatch) => { + dispatch({ + type: SET_SLIPPI_STATUS, + status: status, + }) + } } -export function stopBroadcast() { - // return async (dispatch, getState) => { - broadcastManager.stop(); +export function startBroadcast() { + return async () => { + broadcastManager.start(); + } +} - // dispatch({ - // type: STOP_BROADCAST, - // }) - // } +export function stopBroadcast() { + return async () => { + broadcastManager.stop(); + } } diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index 68ba14958..89cd489c0 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -5,7 +5,7 @@ import WebSocket from 'ws'; import { DolphinConnection, Ports, ConnectionEvent, ConnectionStatus } from '@slippi/slippi-js'; import { store } from '../index'; -import { SET_DOLPHIN_STATUS, SET_SLIPPI_STATUS } from '../actions/broadcast'; +import { setDolphinStatus, setSlippiStatus } from '../actions/broadcast'; import { displayError } from '../actions/error'; const SLIPPI_SERVER = 'ws://localhost:9898/'; @@ -20,10 +20,7 @@ export class BroadcastManager { this.socket = null; this.connection = new DolphinConnection(); this.connection.on(ConnectionEvent.STATUS_CHANGE, status => { - store.dispatch({ - type: SET_DOLPHIN_STATUS, - status: status, - }); + store.dispatch(setDolphinStatus(status)); // Disconnect from Slippi server when we disconnect from Dolphin if (status === ConnectionStatus.DISCONNECTED) { this.stop(); @@ -46,19 +43,13 @@ export class BroadcastManager { // Indicate we're connecting to the Slippi server console.log("Attempting to connect to the Slippi server"); - store.dispatch({ - type: SET_SLIPPI_STATUS, - status: ConnectionStatus.CONNECTING, - }); + store.dispatch(setSlippiStatus(ConnectionStatus.CONNECTING)); this.socket = new WebSocket(SLIPPI_SERVER); this.socket.on('open', () => { // We successfully connected to the Slippi server - store.dispatch({ - type: SET_SLIPPI_STATUS, - status: ConnectionStatus.CONNECTED, - }); + store.dispatch(setSlippiStatus(ConnectionStatus.CONNECTED)); // Now try connect to our local Dolphin instance this.connection.connect( @@ -68,10 +59,8 @@ export class BroadcastManager { }); this.socket.on('close', () => { - store.dispatch({ - type: SET_SLIPPI_STATUS, - status: ConnectionStatus.DISCONNECTED, - }); + store.dispatch(setSlippiStatus(ConnectionStatus.DISCONNECTED)); + // Clear the socket and disconnect from Dolphin too if we're still connected this.socket = null; this.connection.disconnect(); diff --git a/app/reducers/broadcast.js b/app/reducers/broadcast.js index a39926c1d..42858ef63 100644 --- a/app/reducers/broadcast.js +++ b/app/reducers/broadcast.js @@ -1,5 +1,5 @@ import { ConnectionStatus } from '@slippi/slippi-js'; -import { START_BROADCAST, STOP_BROADCAST, SET_DOLPHIN_STATUS, SET_SLIPPI_STATUS } from '../actions/broadcast'; +import { SET_DOLPHIN_STATUS, SET_SLIPPI_STATUS } from '../actions/broadcast'; // Default state for this reducer const defaultState = { @@ -12,10 +12,10 @@ const defaultState = { export default function broadcastReducer(state = defaultState, action) { switch (action.type) { - case START_BROADCAST: - return startBroadcast(state, action); - case STOP_BROADCAST: - return stopBroadcast(state, action); + // case START_BROADCAST: + // return startBroadcast(state, action); + // case STOP_BROADCAST: + // return stopBroadcast(state, action); case SET_DOLPHIN_STATUS: return setDolphinStatus(state, action); case SET_SLIPPI_STATUS: @@ -41,6 +41,7 @@ function setDolphinStatus(state, action) { return newState; } +/* function startBroadcast(state) { const newState = { ...state }; newState.startTime = new Date(); @@ -53,3 +54,4 @@ function stopBroadcast(state) { newState.endTime = new Date(); return newState; } +*/ \ No newline at end of file From 6c96622e1cd9f116ac7751d9349d96778f0a97d9 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Fri, 11 Sep 2020 12:57:56 +1000 Subject: [PATCH 06/87] Improve handling of broadcasting and connection status --- app/components/Broadcast.js | 19 ++++++++++++------- app/reducers/broadcast.js | 29 +++++++++++++++-------------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 2dd633139..1fdd90dfb 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -1,3 +1,5 @@ +/* eslint-disable no-nested-ternary */ + import React, { Component } from 'react'; import PropTypes from 'prop-types'; @@ -48,10 +50,11 @@ export default class Broadcast extends Component { } renderButton() { - const { isBroadcasting } = this.props.broadcast; - const buttonText = isBroadcasting ? "Stop Broadcast" : "Start Broadcast"; + const { isConnecting, isBroadcasting } = this.props.broadcast; + const active = isConnecting || isBroadcasting; + const buttonText = active ? "Stop Broadcast" : "Start Broadcast"; const onClick = () => { - if (isBroadcasting) { + if (active) { this.props.stopBroadcast(); } else { this.props.startBroadcast(); @@ -69,17 +72,17 @@ export default class Broadcast extends Component { } renderContent() { - const { slippiConnectionStatus, dolphinConnectionStatus, startTime, endTime, isBroadcasting } = this.props.broadcast; + const { slippiConnectionStatus, dolphinConnectionStatus, startTime, endTime, isConnecting, isBroadcasting } = this.props.broadcast; console.log(JSON.stringify(this.props)); return (
{this.renderGlobalError()} {this.renderButton()} -
start: {JSON.stringify(startTime)}
-
end: {JSON.stringify(endTime)}
+
Status: {isBroadcasting ? `broadcasting since ${JSON.stringify(startTime)}` : endTime ? `broadcast lasted ${(endTime - startTime) / 1000} seconds` : "not broadcasting"}
dolphin connection status: {JSON.stringify(dolphinConnectionStatus)}
slippi connection status: {JSON.stringify(slippiConnectionStatus)}
-
isbroadcasting: {JSON.stringify(isBroadcasting)}
+
isBroadcasting: {JSON.stringify(isBroadcasting)}
+
isConnecting: {JSON.stringify(isConnecting)}
); } @@ -101,3 +104,5 @@ export default class Broadcast extends Component { ); } } + +/* eslint-enable no-nested-ternary */ \ No newline at end of file diff --git a/app/reducers/broadcast.js b/app/reducers/broadcast.js index 42858ef63..d4387a40f 100644 --- a/app/reducers/broadcast.js +++ b/app/reducers/broadcast.js @@ -8,6 +8,7 @@ const defaultState = { dolphinConnectionStatus: ConnectionStatus.DISCONNECTED, slippiConnectionStatus: ConnectionStatus.DISCONNECTED, isBroadcasting: false, + isConnecting: false, }; export default function broadcastReducer(state = defaultState, action) { @@ -30,7 +31,7 @@ function setSlippiStatus(state, action) { const { status } = action; newState.slippiConnectionStatus = status; newState.isBroadcasting = newState.slippiConnectionStatus === ConnectionStatus.CONNECTED && newState.dolphinConnectionStatus === ConnectionStatus.CONNECTED; - return newState; + return updateBroadcastStatus(state, newState); } function setDolphinStatus(state, action) { @@ -38,20 +39,20 @@ function setDolphinStatus(state, action) { const { status } = action; newState.dolphinConnectionStatus = status; newState.isBroadcasting = newState.slippiConnectionStatus === ConnectionStatus.CONNECTED && newState.dolphinConnectionStatus === ConnectionStatus.CONNECTED; - return newState; + return updateBroadcastStatus(state, newState); } -/* -function startBroadcast(state) { +function updateBroadcastStatus(oldState, state) { const newState = { ...state }; - newState.startTime = new Date(); - newState.endTime = null; - return newState; -} - -function stopBroadcast(state) { - const newState = { ...state }; - newState.endTime = new Date(); + newState.isBroadcasting = newState.slippiConnectionStatus === ConnectionStatus.CONNECTED && newState.dolphinConnectionStatus === ConnectionStatus.CONNECTED; + newState.isConnecting = !newState.isBroadcasting && (newState.slippiConnectionStatus !== ConnectionStatus.DISCONNECTED || newState.dolphinConnectionStatus !== ConnectionStatus.DISCONNECTED); + if (!oldState.isBroadcasting && newState.isBroadcasting) { + // We just started broadcasting + newState.startTime = new Date(); + newState.endTime = null; + } else if (oldState.isBroadcasting && !newState.isBroadcasting) { + // We just stopped broadcasting + newState.endTime = new Date(); + } return newState; -} -*/ \ No newline at end of file +} \ No newline at end of file From 362bf58cc9cc905972ee41827fc448c40e5b43e7 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 16 Sep 2020 11:14:35 +1000 Subject: [PATCH 07/87] Add dotenv for firebase configuration --- .env.example | 8 + .gitignore | 2 + configs/webpack.config.base.js | 5 + package.json | 2 + yarn.lock | 756 ++++++++++++++++++++++++++++++++- 5 files changed, 763 insertions(+), 10 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..42108ddbf --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +REACT_APP_FIREBASE_API_KEY=example +REACT_APP_FIREBASE_AUTH_DOMAIN=example +REACT_APP_FIREBASE_DATABASE_URL=example +REACT_APP_FIREBASE_PROJECT_ID=example +REACT_APP_FIREBASE_STORAGE_BUCKET=example +REACT_APP_FIREBASE_MESSAGING_SENDER_ID=example +REACT_APP_FIREBASE_APP_ID=example +REACT_APP_FIREBASE_MEASUREMENT_ID=example \ No newline at end of file diff --git a/.gitignore b/.gitignore index d69ae7222..d09a9aab1 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,5 @@ main.js.map npm-debug.log.* dolphin/ + +.env \ No newline at end of file diff --git a/configs/webpack.config.base.js b/configs/webpack.config.base.js index 9f285ec07..e76ea545e 100644 --- a/configs/webpack.config.base.js +++ b/configs/webpack.config.base.js @@ -4,6 +4,7 @@ import path from 'path'; import webpack from 'webpack'; +import Dotenv from 'dotenv-webpack'; import { dependencies } from '../package.json'; export default { @@ -43,5 +44,9 @@ export default { }), new webpack.NamedModulesPlugin(), + + new Dotenv({ + path: '../.env', + }), ], }; diff --git a/package.json b/package.json index 82c0489f7..8778ad7f7 100644 --- a/package.json +++ b/package.json @@ -201,6 +201,7 @@ "cross-spawn": "^6.0.5", "css-loader": "^1.0.1", "detect-port": "^1.3.0", + "dotenv-webpack": "^2.0.0", "electron": "^4.1.4", "electron-builder": "^20.34.0", "electron-devtools-installer": "^2.2.4", @@ -263,6 +264,7 @@ "electron-settings": "^3.2.0", "electron-sudo": "^4.0.12", "electron-updater": "^4.0.6", + "firebase": "^7.20.0", "fs-extra": "^8.1.0", "history": "^4.7.2", "ini": "^1.3.5", diff --git a/yarn.lock b/yarn.lock index 93b388a7f..b30d7dbb6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -938,6 +938,230 @@ lodash "^4.17.10" to-fast-properties "^2.0.0" +"@firebase/analytics-types@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.4.0.tgz#d6716f9fa36a6e340bc0ecfe68af325aa6f60508" + integrity sha512-Jj2xW+8+8XPfWGkv9HPv/uR+Qrmq37NPYT352wf7MvE9LrstpLVmFg3LqG6MCRr5miLAom5sen2gZ+iOhVDeRA== + +"@firebase/analytics@0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.5.0.tgz#587292ec9a24410ad795a65c07fb1ea238ccef95" + integrity sha512-WyQ8BT6JSoXpg4q7SV9Yg5EPXbGbG8FkkXAIhV/AnslCglhpxegO1FU33qbuT4Grzc525hZJA97oqtQS8tm4Wg== + dependencies: + "@firebase/analytics-types" "0.4.0" + "@firebase/component" "0.1.19" + "@firebase/installations" "0.4.17" + "@firebase/logger" "0.2.6" + "@firebase/util" "0.3.2" + tslib "^1.11.1" + +"@firebase/app-types@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.6.1.tgz#dcbd23030a71c0c74fc95d4a3f75ba81653850e9" + integrity sha512-L/ZnJRAq7F++utfuoTKX4CLBG5YR7tFO3PLzG1/oXXKEezJ0kRL3CMRoueBEmTCzVb/6SIs2Qlaw++uDgi5Xyg== + +"@firebase/app@0.6.11": + version "0.6.11" + resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.6.11.tgz#f73f9e4571ba62f4029d8f9c9880a97e5a94eb1d" + integrity sha512-FH++PaoyTzfTAVuJ0gITNYEIcjT5G+D0671La27MU8Vvr6MTko+5YUZ4xS9QItyotSeRF4rMJ1KR7G8LSyySiA== + dependencies: + "@firebase/app-types" "0.6.1" + "@firebase/component" "0.1.19" + "@firebase/logger" "0.2.6" + "@firebase/util" "0.3.2" + dom-storage "2.1.0" + tslib "^1.11.1" + xmlhttprequest "1.8.0" + +"@firebase/auth-interop-types@0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.1.5.tgz#9fc9bd7c879f16b8d1bb08373a0f48c3a8b74557" + integrity sha512-88h74TMQ6wXChPA6h9Q3E1Jg6TkTHep2+k63OWg3s0ozyGVMeY+TTOti7PFPzq5RhszQPQOoCi59es4MaRvgCw== + +"@firebase/auth-types@0.10.1": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.10.1.tgz#7815e71c9c6f072034415524b29ca8f1d1770660" + integrity sha512-/+gBHb1O9x/YlG7inXfxff/6X3BPZt4zgBv4kql6HEmdzNQCodIRlEYnI+/da+lN+dha7PjaFH7C7ewMmfV7rw== + +"@firebase/auth@0.14.9": + version "0.14.9" + resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.14.9.tgz#481db24d5bd6eded8ac2e5aea6edb9307040229c" + integrity sha512-PxYa2r5qUEdheXTvqROFrMstK8W4uPiP7NVfp+2Bec+AjY5PxZapCx/YFDLkU0D7YBI82H74PtZrzdJZw7TJ4w== + dependencies: + "@firebase/auth-types" "0.10.1" + +"@firebase/component@0.1.19": + version "0.1.19" + resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.1.19.tgz#bd2ac601652c22576b574c08c40da245933dbac7" + integrity sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ== + dependencies: + "@firebase/util" "0.3.2" + tslib "^1.11.1" + +"@firebase/database-types@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.5.2.tgz#23bec8477f84f519727f165c687761e29958b63c" + integrity sha512-ap2WQOS3LKmGuVFKUghFft7RxXTyZTDr0Xd8y2aqmWsbJVjgozi0huL/EUMgTjGFrATAjcf2A7aNs8AKKZ2a8g== + dependencies: + "@firebase/app-types" "0.6.1" + +"@firebase/database@0.6.12": + version "0.6.12" + resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.6.12.tgz#60b484d34add1c0aad4999e2b1cb58b8f2b707c6" + integrity sha512-OLUxp8TkXiML4X5LWM5IACsSDvo3fcf4mTbTe5RF+N6TRFv0Svzlet5OgGIa3ET1dQvNiisrMX7zzRa0OTLs7Q== + dependencies: + "@firebase/auth-interop-types" "0.1.5" + "@firebase/component" "0.1.19" + "@firebase/database-types" "0.5.2" + "@firebase/logger" "0.2.6" + "@firebase/util" "0.3.2" + faye-websocket "0.11.3" + tslib "^1.11.1" + +"@firebase/firestore-types@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-1.12.1.tgz#67e999798043d1b3156d0a2c52d4299a92345deb" + integrity sha512-CpWcDriYnGDoAl0D9DcSuwX0b/fXqi7qOwuuTI1M0SYxau48G8cqhVjzjqPDgEM3kDGYJTnPN3ALS0Z4cnwERQ== + +"@firebase/firestore@1.16.7": + version "1.16.7" + resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-1.16.7.tgz#046da8e129205538335f261b804273ec04c6df42" + integrity sha512-MrX7te1eUib2pUzD3dLWdRuM7EPcCxtPwO4M9og3IFYr1U3XlxybD7kxyYswltHcUm6+kba3VKL1rvkqZ1sn2g== + dependencies: + "@firebase/component" "0.1.19" + "@firebase/firestore-types" "1.12.1" + "@firebase/logger" "0.2.6" + "@firebase/util" "0.3.2" + "@firebase/webchannel-wrapper" "0.3.0" + "@grpc/grpc-js" "^1.0.0" + "@grpc/proto-loader" "^0.5.0" + node-fetch "2.6.0" + tslib "^1.11.1" + +"@firebase/functions-types@0.3.17": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.3.17.tgz#348bf5528b238eeeeeae1d52e8ca547b21d33a94" + integrity sha512-DGR4i3VI55KnYk4IxrIw7+VG7Q3gA65azHnZxo98Il8IvYLr2UTBlSh72dTLlDf25NW51HqvJgYJDKvSaAeyHQ== + +"@firebase/functions@0.4.51": + version "0.4.51" + resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.4.51.tgz#97be571cfe3b9ee3bf289b9dc5194e3ae49a4819" + integrity sha512-PPx8eZcr4eoU9BITOUGUVurs4WZu8Thj3uCWx766dU3mV1W/7kRgtiptmW0XJUB18FZ1PT3+Hadd6V6vjtLgYw== + dependencies: + "@firebase/component" "0.1.19" + "@firebase/functions-types" "0.3.17" + "@firebase/messaging-types" "0.5.0" + isomorphic-fetch "2.2.1" + tslib "^1.11.1" + +"@firebase/installations-types@0.3.4": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.3.4.tgz#589a941d713f4f64bf9f4feb7f463505bab1afa2" + integrity sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q== + +"@firebase/installations@0.4.17": + version "0.4.17" + resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.4.17.tgz#1367b721e2c6c4880646bbc4f257e8616986a004" + integrity sha512-AE/TyzIpwkC4UayRJD419xTqZkKzxwk0FLht3Dci8WI2OEKHSwoZG9xv4hOBZebe+fDzoV2EzfatQY8c/6Avig== + dependencies: + "@firebase/component" "0.1.19" + "@firebase/installations-types" "0.3.4" + "@firebase/util" "0.3.2" + idb "3.0.2" + tslib "^1.11.1" + +"@firebase/logger@0.2.6": + version "0.2.6" + resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.2.6.tgz#3aa2ca4fe10327cabf7808bd3994e88db26d7989" + integrity sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw== + +"@firebase/messaging-types@0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@firebase/messaging-types/-/messaging-types-0.5.0.tgz#c5d0ef309ced1758fda93ef3ac70a786de2e73c4" + integrity sha512-QaaBswrU6umJYb/ZYvjR5JDSslCGOH6D9P136PhabFAHLTR4TWjsaACvbBXuvwrfCXu10DtcjMxqfhdNIB1Xfg== + +"@firebase/messaging@0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.7.1.tgz#debbe7eb17c5b789231da6c166c506e19ecf1ed4" + integrity sha512-iev/ST9v0xd/8YpGYrZtDcqdD9J6ZWzSuceRn8EKy5vIgQvW/rk2eTQc8axzvDpQ36ZfphMYuhW6XuNrR3Pd2Q== + dependencies: + "@firebase/component" "0.1.19" + "@firebase/installations" "0.4.17" + "@firebase/messaging-types" "0.5.0" + "@firebase/util" "0.3.2" + idb "3.0.2" + tslib "^1.11.1" + +"@firebase/performance-types@0.0.13": + version "0.0.13" + resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.0.13.tgz#58ce5453f57e34b18186f74ef11550dfc558ede6" + integrity sha512-6fZfIGjQpwo9S5OzMpPyqgYAUZcFzZxHFqOyNtorDIgNXq33nlldTL/vtaUZA8iT9TT5cJlCrF/jthKU7X21EA== + +"@firebase/performance@0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.4.1.tgz#4e78f406ef2bc0eec2ce67cdfc57a53a55c31476" + integrity sha512-eAqS3/456xnUwuTg4w58x2fYbvTtQpgt67lpBUX3DuhOqwiM8+JELRte52nDgum2lTaTZWiu5de9mPuAYx2WDg== + dependencies: + "@firebase/component" "0.1.19" + "@firebase/installations" "0.4.17" + "@firebase/logger" "0.2.6" + "@firebase/performance-types" "0.0.13" + "@firebase/util" "0.3.2" + tslib "^1.11.1" + +"@firebase/polyfill@0.3.36": + version "0.3.36" + resolved "https://registry.yarnpkg.com/@firebase/polyfill/-/polyfill-0.3.36.tgz#c057cce6748170f36966b555749472b25efdb145" + integrity sha512-zMM9oSJgY6cT2jx3Ce9LYqb0eIpDE52meIzd/oe/y70F+v9u1LDqk5kUF5mf16zovGBWMNFmgzlsh6Wj0OsFtg== + dependencies: + core-js "3.6.5" + promise-polyfill "8.1.3" + whatwg-fetch "2.0.4" + +"@firebase/remote-config-types@0.1.9": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.1.9.tgz#fe6bbe4d08f3b6e92fce30e4b7a9f4d6a96d6965" + integrity sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA== + +"@firebase/remote-config@0.1.28": + version "0.1.28" + resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.1.28.tgz#1c39916446f1ed82b4c07e556455bd232fcfd8e1" + integrity sha512-4zSdyxpt94jAnFhO8toNjG8oMKBD+xTuBIcK+Nw8BdQWeJhEamgXlupdBARUk1uf3AvYICngHH32+Si/dMVTbw== + dependencies: + "@firebase/component" "0.1.19" + "@firebase/installations" "0.4.17" + "@firebase/logger" "0.2.6" + "@firebase/remote-config-types" "0.1.9" + "@firebase/util" "0.3.2" + tslib "^1.11.1" + +"@firebase/storage-types@0.3.13": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.3.13.tgz#cd43e939a2ab5742e109eb639a313673a48b5458" + integrity sha512-pL7b8d5kMNCCL0w9hF7pr16POyKkb3imOW7w0qYrhBnbyJTdVxMWZhb0HxCFyQWC0w3EiIFFmxoz8NTFZDEFog== + +"@firebase/storage@0.3.43": + version "0.3.43" + resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.3.43.tgz#107fb5db2eff2561b5c4e35ee4cbff48f28c7e77" + integrity sha512-Jp54jcuyimLxPhZHFVAhNbQmgTu3Sda7vXjXrNpPEhlvvMSq4yuZBR6RrZxe/OrNVprLHh/6lTCjwjOVSo3bWA== + dependencies: + "@firebase/component" "0.1.19" + "@firebase/storage-types" "0.3.13" + "@firebase/util" "0.3.2" + tslib "^1.11.1" + +"@firebase/util@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@firebase/util/-/util-0.3.2.tgz#87de27f9cffc2324651cabf6ec133d0a9eb21b52" + integrity sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g== + dependencies: + tslib "^1.11.1" + +"@firebase/webchannel-wrapper@0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.3.0.tgz#d1689566b94c25423d1fb2cb031c5c2ea4c9f939" + integrity sha512-VniCGPIgSGNEgOkh5phb3iKmSGIzcwrccy3IomMFRWPCMiCk2y98UQNJEoDs1yIHtZMstVjYWKYxnunIGzC5UQ== + "@fortawesome/fontawesome-free@^5.5.0": version "5.6.3" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.6.3.tgz#61c122c420d7a91613f393d6a06e5a4c6ae6abf3" @@ -1007,6 +1231,35 @@ through2 "^3.0.0" xdg-basedir "^3.0.0" +"@grpc/grpc-js@^1.0.0": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.1.6.tgz#43ab7bcb1aec071e18d7b45f8920afc0c9fcfb8e" + integrity sha512-bUeaMN/dHTkt9AqU0Tc1xdHMB3jVLyPNfg8gZ5cMyhFyMeCwoJbFcJrNBgYqRCbvYhvtaEgzQwkw91NnY4Oktg== + dependencies: + "@grpc/proto-loader" "^0.6.0-pre14" + "@types/node" "^12.12.47" + google-auth-library "^6.0.0" + semver "^6.2.0" + +"@grpc/proto-loader@^0.5.0": + version "0.5.5" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.5.tgz#6725e7a1827bdf8e92e29fbf4e9ef0203c0906a9" + integrity sha512-WwN9jVNdHRQoOBo9FDH7qU+mgfjPc8GygPYms3M+y3fbQLfnCe/Kv/E01t7JRgnrsOHH8euvSbed3mIalXhwqQ== + dependencies: + lodash.camelcase "^4.3.0" + protobufjs "^6.8.6" + +"@grpc/proto-loader@^0.6.0-pre14": + version "0.6.0-pre9" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.6.0-pre9.tgz#0c6fe42f6c5ef9ce1b3cef7be64d5b09d6fe4d6d" + integrity sha512-oM+LjpEjNzW5pNJjt4/hq1HYayNeQT+eGrOPABJnYHv7TyNPDNzkQ76rDYZF86X5swJOa4EujEMzQ9iiTdPgww== + dependencies: + "@types/long" "^4.0.1" + lodash.camelcase "^4.3.0" + long "^4.0.0" + protobufjs "^6.9.0" + yargs "^15.3.1" + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -1020,6 +1273,59 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78= + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A= + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU= + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E= + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik= + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0= + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q= + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= + "@semantic-ui-react/event-stack@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@semantic-ui-react/event-stack/-/event-stack-3.0.1.tgz#41d0b095ac94cc5e1607a4fed4d0f8860d0d2e60" @@ -1073,6 +1379,11 @@ resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.1.tgz#9794c69c8385d0192acc471a540d1f8e0d16218a" integrity sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A== +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + "@types/duplexify@^3.5.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@types/duplexify/-/duplexify-3.6.0.tgz#dfc82b64bd3a2168f5bd26444af165bf0237dcd8" @@ -1097,6 +1408,11 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.119.tgz#be847e5f4bc3e35e46d041c394ead8b603ad8b39" integrity sha512-Z3TNyBL8Vd/M9D9Ms2S3LmFq2sSMzahodD6rCS9V2N44HUMINb75jNkSuwAx7eo2ufqTdfOdtGQpNbieUjPQmw== +"@types/long@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" + integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== + "@types/node@*": version "10.12.18" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" @@ -1107,6 +1423,16 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.4.tgz#1c586b991457cbb58fef51bc4e0cfcfa347714b5" integrity sha512-DT25xX/YgyPKiHFOpNuANIQIVvYEwCWXgK2jYYwqgaMrYE6+tq+DtmMwlD3drl6DJbUwtlIDnn0d7tIn/EbXBg== +"@types/node@^12.12.47": + version "12.12.59" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.59.tgz#3a6154c24d4b5bd95bb1ce921ef805fb722f24cc" + integrity sha512-D2MISWfv2j17aFBAkMD3lQ97vYpXCkAJMJf0mx2eKHNkzXA6Vo9w7A7BWi9fH8sOH1zeFb7fIhOo22z0TtrSag== + +"@types/node@^13.7.0": + version "13.13.20" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.20.tgz#8196a4db574220fc50e2e54f250ad51179bd0a03" + integrity sha512-1kx55tU3AvGX2Cjk2W4GMBxbgIz892V+X10S2gUreIAq8qCWgaQH+tZBOWc0bi2BKFhQt+CX0BTx28V9QPNa+A== + "@types/q@^1.5.1": version "1.5.1" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18" @@ -1297,6 +1623,13 @@ abort-controller@^2.0.2: dependencies: event-target-shim "^5.0.0" +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + accepts@~1.3.4, accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" @@ -1350,6 +1683,13 @@ address@^1.0.1: resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" integrity sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg== +agent-base@6: + version "6.0.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.1.tgz#808007e4e5867decb0ab6ab2f928fbdb5a596db4" + integrity sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg== + dependencies: + debug "4" + agent-base@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" @@ -1457,6 +1797,11 @@ ansi-regex@^4.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -1469,6 +1814,14 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + ansi-wrap@0.1.0, ansi-wrap@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" @@ -1692,6 +2045,11 @@ arrify@^1.0.0, arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= +arrify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -2668,6 +3026,11 @@ bignumber.js@^7.0.0: resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== +bignumber.js@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" + integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== + bin-v8-flags-filter@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/bin-v8-flags-filter/-/bin-v8-flags-filter-1.1.3.tgz#14c018c6cca7529767c1f42f12bd3bb20d61e4d3" @@ -3386,6 +3749,15 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + clone-deep@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713" @@ -3453,6 +3825,13 @@ color-convert@^1.9.0, color-convert@^1.9.1: dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-convert@~0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd" @@ -3463,7 +3842,7 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@^1.0.0: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== @@ -3721,6 +4100,11 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= +core-js@3.6.5: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" + integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== + core-js@^1.0.0: version "1.2.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" @@ -4150,6 +4534,13 @@ debug@2.6.9, debug@^2.1.2, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6. dependencies: ms "2.0.0" +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + debug@=3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -4164,13 +4555,6 @@ debug@^3.0.0, debug@^3.1.0, debug@^3.2.5: dependencies: ms "^2.1.1" -debug@^4.0.0, debug@^4.0.1, debug@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - decamelize-keys@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -4460,6 +4844,11 @@ dom-serializer@0, dom-serializer@~0.1.0: domelementtype "~1.1.1" entities "~1.1.1" +dom-storage@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/dom-storage/-/dom-storage-2.1.0.tgz#00fb868bc9201357ea243c7bcfd3304c1e34ea39" + integrity sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q== + dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" @@ -4517,16 +4906,35 @@ dot-prop@^4.1.0, dot-prop@^4.1.1: dependencies: is-obj "^1.0.0" +dotenv-defaults@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/dotenv-defaults/-/dotenv-defaults-2.0.1.tgz#ea6f9632b3b5cc55e48b736760def5561f1cb7c0" + integrity sha512-ugFCyBF7ILuwpmznduHPQZBMucHHJ8T4OBManTEVjemxCm2+nqifSuW2lD2SNKdiKSH1E324kZSdJ8M04b4I/A== + dependencies: + dotenv "^8.2.0" + dotenv-expand@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-4.2.0.tgz#def1f1ca5d6059d24a766e587942c21106ce1275" integrity sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU= +dotenv-webpack@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dotenv-webpack/-/dotenv-webpack-2.0.0.tgz#064ae42dbb214778d8aff0c76dc97253594f9ec3" + integrity sha512-Omo5IpVl7XRgWXeZjxdfqOBEApJPxGLMOIx3F/w/W7ppUKgYMOXrk4eczlQrErPD4X0YRESlyGJek3O4uobRnw== + dependencies: + dotenv-defaults "^2.0.0" + dotenv@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== +dotenv@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" + integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== + duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" @@ -4570,7 +4978,7 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ecdsa-sig-formatter@1.0.11: +ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== @@ -4775,6 +5183,11 @@ emoji-regex@^6.5.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.5.1.tgz#9baea929b155565c11ea41c6626eaa65cef992c2" integrity sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -4785,6 +5198,13 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= +encoding@^0.1.11: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" @@ -5542,6 +5962,13 @@ fastparse@^1.1.1: resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== +faye-websocket@0.11.3: + version "0.11.3" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" + integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== + dependencies: + websocket-driver ">=0.5.1" + faye-websocket@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" @@ -5719,6 +6146,14 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + findup-sync@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" @@ -5729,6 +6164,26 @@ findup-sync@^2.0.0: micromatch "^3.0.4" resolve-dir "^1.0.1" +firebase@^7.20.0: + version "7.20.0" + resolved "https://registry.yarnpkg.com/firebase/-/firebase-7.20.0.tgz#ac1557a0962070d19d61d150c69421a5503710ec" + integrity sha512-ijgiUPB93UGWw2P2kgUQgghu5WOn/WR2J8C/V6ZSeI1PQqiEwsfn0kvw4iMJeqLQpA/FVeZz/+p0ubE5kzqhBA== + dependencies: + "@firebase/analytics" "0.5.0" + "@firebase/app" "0.6.11" + "@firebase/app-types" "0.6.1" + "@firebase/auth" "0.14.9" + "@firebase/database" "0.6.12" + "@firebase/firestore" "1.16.7" + "@firebase/functions" "0.4.51" + "@firebase/installations" "0.4.17" + "@firebase/messaging" "0.7.1" + "@firebase/performance" "0.4.1" + "@firebase/polyfill" "0.3.36" + "@firebase/remote-config" "0.1.28" + "@firebase/storage" "0.3.43" + "@firebase/util" "0.3.2" + flat-cache@^1.2.1: version "1.3.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" @@ -5940,6 +6395,17 @@ gaxios@^1.0.2, gaxios@^1.0.4, gaxios@^1.2.1: https-proxy-agent "^2.2.1" node-fetch "^2.3.0" +gaxios@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-3.2.0.tgz#11b6f0e8fb08d94a10d4d58b044ad3bec6dd486a" + integrity sha512-+6WPeVzPvOshftpxJwRi2Ozez80tn/hdtOUag7+gajDHRJvAblKxTFSSMPtr2hmnLy7p0mvYz0rMXLBl8pSO7Q== + dependencies: + abort-controller "^3.0.0" + extend "^3.0.2" + https-proxy-agent "^5.0.0" + is-stream "^2.0.0" + node-fetch "^2.3.0" + gaze@^1.0.0, gaze@~1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" @@ -5955,6 +6421,14 @@ gcp-metadata@^0.9.3: gaxios "^1.0.2" json-bigint "^0.3.0" +gcp-metadata@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.2.0.tgz#3b424355ccdc240ee07c5791e2fd6a60a283d89a" + integrity sha512-vQZD57cQkqIA6YPGXM/zc+PIZfNRFdukWGsGZ5+LcJzesi5xp6Gn7a02wRJi4eXPyArNMIYpPET4QMxGqtlk6Q== + dependencies: + gaxios "^3.0.0" + json-bigint "^1.0.0" + gcs-resumable-upload@^0.14.1: version "0.14.1" resolved "https://registry.yarnpkg.com/gcs-resumable-upload/-/gcs-resumable-upload-0.14.1.tgz#d0b0b2acc608d63e4164329b0a1231227383b532" @@ -5971,6 +6445,11 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + get-func-name@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" @@ -6183,6 +6662,21 @@ google-auth-library@^3.0.0: lru-cache "^5.0.0" semver "^5.5.0" +google-auth-library@^6.0.0: + version "6.0.6" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-6.0.6.tgz#5102e5c643baab45b4c16e9752cd56b8861f3a82" + integrity sha512-fWYdRdg55HSJoRq9k568jJA1lrhg9i2xgfhVIMJbskUmbDpJGHsbv9l41DGhCDXM21F9Kn4kUwdysgxSYBYJUw== + dependencies: + arrify "^2.0.0" + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + fast-text-encoding "^1.0.0" + gaxios "^3.0.0" + gcp-metadata "^4.1.0" + gtoken "^5.0.0" + jws "^4.0.0" + lru-cache "^6.0.0" + google-p12-pem@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-1.0.3.tgz#3d8acc140573339a5bca7b2f6a4b206bbea6d8d7" @@ -6191,6 +6685,13 @@ google-p12-pem@^1.0.0: node-forge "^0.7.5" pify "^4.0.0" +google-p12-pem@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.0.3.tgz#673ac3a75d3903a87f05878f3c75e06fc151669e" + integrity sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA== + dependencies: + node-forge "^0.10.0" + got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" @@ -6246,6 +6747,16 @@ gtoken@^2.3.2: mime "^2.2.0" pify "^4.0.0" +gtoken@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.0.3.tgz#b76ef8e9a2fed6fef165e47f7d05b60c498e4d05" + integrity sha512-Nyd1wZCMRc2dj/mAD0LlfQLcAO06uKdpKJXvK85SGrF5+5+Bpfil9u/2aw35ltvEHjvl0h5FMKN5knEU+9JrOg== + dependencies: + gaxios "^3.0.0" + google-p12-pem "^3.0.0" + jws "^4.0.0" + mime "^2.2.0" + gulp-clone@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/gulp-clone/-/gulp-clone-2.0.1.tgz#cf4ecb28ca46d032f6949271e8bf7986e78e6ff9" @@ -6604,6 +7115,14 @@ https-proxy-agent@^2.2.1: agent-base "^4.1.0" debug "^3.1.0" +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + humanize-plus@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/humanize-plus/-/humanize-plus-1.8.2.tgz#a65b34459ad6367adbb3707a82a3c9f916167030" @@ -6663,6 +7182,11 @@ icss-utils@^2.1.0: dependencies: postcss "^6.0.1" +idb@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/idb/-/idb-3.0.2.tgz#c8e9122d5ddd40f13b60ae665e4862f8b13fa384" + integrity sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw== + identity-obj-proxy@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" @@ -7119,6 +7643,11 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-generator-fn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a" @@ -7275,11 +7804,16 @@ is-stream-ended@^0.1.4: resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw== -is-stream@^1.0.0, is-stream@^1.1.0: +is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + is-string@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.4.tgz#cc3a9b69857d621e963725a24caeec873b826e64" @@ -7378,6 +7912,14 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= +isomorphic-fetch@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -7874,6 +8416,13 @@ json-bigint@^0.3.0: dependencies: bignumber.js "^7.0.0" +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -7961,6 +8510,15 @@ jwa@^1.2.0: ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" +jwa@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" + integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + jws@^3.1.5: version "3.2.1" resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.1.tgz#d79d4216a62c9afa0a3d5e8b5356d75abdeb2be5" @@ -7969,6 +8527,14 @@ jws@^3.1.5: jwa "^1.2.0" safe-buffer "^5.0.1" +jws@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" + integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + dependencies: + jwa "^2.0.0" + safe-buffer "^5.0.1" + keyboard-key@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/keyboard-key/-/keyboard-key-1.0.2.tgz#212e14dde4c2059814336159bbc5acd0a348ca6b" @@ -8165,6 +8731,18 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -8267,6 +8845,11 @@ lolex@^3.0.0: resolved "https://registry.yarnpkg.com/lolex/-/lolex-3.0.0.tgz#f04ee1a8aa13f60f1abd7b0e8f4213ec72ec193e" integrity sha512-hcnW80h3j2lbUfFdMArd5UPA/vxZJ+G8vobd+wg3nVEQA0EigStbYcrG030FJxL6xiDDPEkoMatV9xIh5OecQQ== +long@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + longest-streak@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e" @@ -8312,6 +8895,13 @@ lru-cache@^5.0.0, lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + make-dir@^1.0.0, make-dir@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" @@ -8865,6 +9455,19 @@ nise@^1.4.7: path-to-regexp "^1.7.0" text-encoding "^0.6.4" +node-fetch@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" + integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== + +node-fetch@^1.0.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + node-fetch@^2.2.0, node-fetch@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.3.0.tgz#1a1d940bbfb916a1d3e0219f037e89e71f8c5fa5" @@ -8875,6 +9478,11 @@ node-forge@0.7.5: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" integrity sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ== +node-forge@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" + integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== + node-forge@^0.7.5: version "0.7.6" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac" @@ -9402,6 +10010,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -9416,6 +10031,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-map@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" @@ -9581,6 +10203,11 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -10274,6 +10901,11 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= +promise-polyfill@8.1.3: + version "8.1.3" + resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.1.3.tgz#8c99b3cf53f3a91c68226ffde7bde81d7f904116" + integrity sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g== + promisify-event@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/promisify-event/-/promisify-event-1.0.0.tgz#bd7523ea06b70162f370979016b53a686c60e90f" @@ -10297,6 +10929,25 @@ prop-types@^15.6.1, prop-types@^15.6.2: loose-envify "^1.3.1" object-assign "^4.1.1" +protobufjs@^6.8.6, protobufjs@^6.9.0: + version "6.10.1" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.1.tgz#e6a484dd8f04b29629e9053344e3970cccf13cd2" + integrity sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.1" + "@types/node" "^13.7.0" + long "^4.0.0" + proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" @@ -11035,6 +11686,11 @@ require-main-filename@^1.0.1: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -11364,6 +12020,11 @@ semver@5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== +semver@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + semver@^7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" @@ -11918,6 +12579,15 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + string.prototype.trim@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" @@ -11977,6 +12647,13 @@ strip-ansi@^5.0.0: dependencies: ansi-regex "^4.0.0" +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + strip-bom@3.0.0, strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -12775,6 +13452,11 @@ tryer@^1.0.0: resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== +tslib@^1.11.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" + integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + tslib@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" @@ -13437,6 +14119,16 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: dependencies: iconv-lite "0.4.24" +whatwg-fetch@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== + +whatwg-fetch@>=0.10.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz#e5f871572d6879663fa5674c8f833f15a8425ab3" + integrity sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ== + whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" @@ -13533,6 +14225,15 @@ wrap-ansi@^3.0.1: string-width "^2.1.1" strip-ansi "^4.0.0" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -13609,6 +14310,11 @@ xmldom@0.1.x: resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk= +xmlhttprequest@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= + xregexp@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" @@ -13646,6 +14352,11 @@ yallist@^3.0.0, yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@^10.0.0, yargs-parser@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" @@ -13661,6 +14372,14 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" @@ -13729,6 +14448,23 @@ yargs@^12.0.1, yargs@^12.0.4, yargs@^12.0.5: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" +yargs@^15.3.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + yargs@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" From 10f7364f491c2d38c411abbc706cacd75abccc4a Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 16 Sep 2020 12:28:21 +1000 Subject: [PATCH 08/87] Add working firebase authentication --- .env.example | 16 +-- app/actions/auth.js | 24 +++++ app/components/Settings.js | 149 ++++++++++++++++++++------- app/containers/SettingsPage.js | 4 +- app/domain/FirebaseAuthentication.js | 24 +++++ app/index.js | 3 + app/reducers/auth.js | 22 ++++ app/reducers/index.js | 2 + configs/webpack.config.base.js | 4 +- 9 files changed, 196 insertions(+), 52 deletions(-) create mode 100644 app/actions/auth.js create mode 100644 app/domain/FirebaseAuthentication.js create mode 100644 app/reducers/auth.js diff --git a/.env.example b/.env.example index 42108ddbf..4931e5b11 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,8 @@ -REACT_APP_FIREBASE_API_KEY=example -REACT_APP_FIREBASE_AUTH_DOMAIN=example -REACT_APP_FIREBASE_DATABASE_URL=example -REACT_APP_FIREBASE_PROJECT_ID=example -REACT_APP_FIREBASE_STORAGE_BUCKET=example -REACT_APP_FIREBASE_MESSAGING_SENDER_ID=example -REACT_APP_FIREBASE_APP_ID=example -REACT_APP_FIREBASE_MEASUREMENT_ID=example \ No newline at end of file +FIREBASE_API_KEY=example +FIREBASE_AUTH_DOMAIN=example +FIREBASE_DATABASE_URL=example +FIREBASE_PROJECT_ID=example +FIREBASE_STORAGE_BUCKET=example +FIREBASE_MESSAGING_SENDER_ID=example +FIREBASE_APP_ID=example +FIREBASE_MEASUREMENT_ID=example \ No newline at end of file diff --git a/app/actions/auth.js b/app/actions/auth.js new file mode 100644 index 000000000..ec1175c42 --- /dev/null +++ b/app/actions/auth.js @@ -0,0 +1,24 @@ +import { auth } from 'firebase'; + +export const SET_AUTH_USER = 'SET_AUTH_USER'; + +export function setAuthUser(user) { + return async (dispatch) => { + dispatch({ + type: SET_AUTH_USER, + user: user, + }) + } +} + +export function login(email, password) { + return async () => { + await auth().signInWithEmailAndPassword(email, password); + } +} + +export function logout() { + return async () => { + await auth().signOut(); + } +} diff --git a/app/components/Settings.js b/app/components/Settings.js index 66735b39d..eede0d93f 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -1,13 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import _ from 'lodash'; -import { - Button, - Message, - Header, - Icon, - Confirm, -} from 'semantic-ui-react'; +import { Button, Message, Header, Icon, Confirm } from 'semantic-ui-react'; import { getDefaultDolphinPath } from '../utils/settings'; import PageHeader from './common/PageHeader'; import ActionInput from './common/ActionInput'; @@ -30,6 +24,8 @@ export default class Settings extends Component { openDolphin: PropTypes.func.isRequired, resetDolphin: PropTypes.func.isRequired, setResetConfirm: PropTypes.func.isRequired, + login: PropTypes.func.isRequired, + logout: PropTypes.func.isRequired, // error actions dismissError: PropTypes.func.isRequired, @@ -37,10 +33,19 @@ export default class Settings extends Component { // store data history: PropTypes.object.isRequired, store: PropTypes.object.isRequired, + auth: PropTypes.object.isRequired, errors: PropTypes.object.isRequired, topNotifOffset: PropTypes.number.isRequired, }; + constructor() { + super(); + this.state = { + email: '', + password: '', + }; + } + componentDidMount() { this.props.validateISO(); } @@ -78,8 +83,9 @@ export default class Settings extends Component { const contentMsg = (
Hello Linux friend! We now include a Dolphin build that will probably - work on your distro. If it doesn't work, you will have to build your own. - Please find the Playback Dolphin Path  option to configure. + work on your distro. If it doesn't work, you will have to build + your own. Please find the Playback Dolphin Path  option to + configure. Join the discord  @@ -97,6 +103,49 @@ export default class Settings extends Component { ); } + renderUserBlock() { + const auth = this.props.auth || {}; + + if (!auth.user) { + return ( +
+ +
+ + this.setState({ email: e.target.value })} + /> +
+
+ + this.setState({ password: e.target.value })} + /> +
+
+ ); + } + return

Welcome {auth.user.displayName}

; + } + renderConfigDolphin() { const store = this.props.store || {}; @@ -163,56 +212,59 @@ export default class Settings extends Component { onCancel={this.hideConfirmReset} />
- ) + ); } showConfirmReset = () => { this.props.setResetConfirm(true); - } + }; confirmResetDolphin = () => { this.hideConfirmReset(); this.props.resetDolphin(); - } + }; hideConfirmReset = () => { this.props.setResetConfirm(false); - } + }; renderISOVersionCheck() { - const validationState = _.get(this.props.store, 'isoValidationState') || 'unknown'; + const validationState = + _.get(this.props.store, 'isoValidationState') || 'unknown'; let icon, text, loading; switch (validationState) { - case "success": - icon = "check circle outline"; - text = "Valid"; + case 'success': + icon = 'check circle outline'; + text = 'Valid'; loading = false; break; - case "fail": - icon = "times circle outline"; - text = "Bad ISO"; + case 'fail': + icon = 'times circle outline'; + text = 'Bad ISO'; loading = false; break; - case "unknown": - icon = "warning sign" - text = "Unknown ISO"; + case 'unknown': + icon = 'warning sign'; + text = 'Unknown ISO'; loading = false; break; - case "validating": - icon = "spinner"; - text = "Verifying"; + case 'validating': + icon = 'spinner'; + text = 'Verifying'; loading = true; break; default: - icon = "question circle outline"; - text = ""; + icon = 'question circle outline'; + text = ''; loading = false; break; } return ( -
+
{text}
@@ -230,7 +282,7 @@ export default class Settings extends Component { label="Melee ISO File" description="The path to a NTSC Melee 1.02 ISO. Used for playing replay files" value={store.settings.isoPath} - error={isoValidationState === "fail"} + error={isoValidationState === 'fail'} onClick={this.props.browseFile} handlerParams={['isoPath']} disabled={store.isResetting} @@ -262,10 +314,8 @@ export default class Settings extends Component { renderAdvancedSettings() { const inputs = []; - - inputs.push([ - this.renderPlaybackInstanceInput(), - ]); + + inputs.push([this.renderPlaybackInstanceInput()]); if (_.isEmpty(inputs)) { // Don't show advanced toggle if there are no @@ -291,8 +341,8 @@ export default class Settings extends Component { const playbackDolphinDescription = (
- An instance of Dolphin for playing replays comes bundled - with this app. This setting allows you to configure a different instance. + An instance of Dolphin for playing replays comes bundled with this app. + This setting allows you to configure a different instance.
); @@ -311,9 +361,16 @@ export default class Settings extends Component { label="Playback Dolphin Path" description={playbackDolphinDescription} /> - + - The default should be used by almost everyone. Only modify if you know what you are doing + + The default should be used by almost everyone. Only modify if you + know what you are doing +
- ) + ); + } + + renderUserAuth() { + return ( +
+
Connect with Slippi.gg
+ + {this.renderUserBlock()} + +
+ ); } renderContent() { @@ -350,6 +418,7 @@ export default class Settings extends Component { {this.renderBasicSettings()} {this.renderAdvancedSettings()} {this.renderActions()} + {this.renderUserAuth()} ); } @@ -373,4 +442,4 @@ export default class Settings extends Component { ); } -} \ No newline at end of file +} diff --git a/app/containers/SettingsPage.js b/app/containers/SettingsPage.js index fb8bec8a5..291324605 100644 --- a/app/containers/SettingsPage.js +++ b/app/containers/SettingsPage.js @@ -3,18 +3,20 @@ import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import Settings from '../components/Settings'; import * as SettingsActions from '../actions/settings'; +import * as AuthActions from '../actions/auth'; import * as ErrorActions from '../actions/error'; function mapStateToProps(state) { return { store: state.settings, + auth: state.auth, errors: state.errors, topNotifOffset: _.get(state.notifs, ['activeNotif', 'heightPx']) || 0, }; } function mapDispatchToProps(dispatch) { - const allActions = _.extend({}, SettingsActions, ErrorActions); + const allActions = _.extend({}, AuthActions, SettingsActions, ErrorActions); return bindActionCreators(allActions, dispatch); } diff --git a/app/domain/FirebaseAuthentication.js b/app/domain/FirebaseAuthentication.js new file mode 100644 index 000000000..f10272971 --- /dev/null +++ b/app/domain/FirebaseAuthentication.js @@ -0,0 +1,24 @@ +import firebase from "firebase"; + +import { setAuthUser } from '../actions/auth'; +import { store } from "../index"; + +const firebaseConfig = { + apiKey: process.env.FIREBASE_API_KEY, + authDomain: process.env.FIREBASE_AUTH_DOMAIN, + databaseURL: process.env.FIREBASE_DATABASE_URL, + projectId: process.env.FIREBASE_PROJECT_ID, + storageBucket: process.env.FIREBASE_STORAGE_BUCKET, + messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID, + appId: process.env.FIREBASE_APP_ID, + measurementId: process.env.FIREBASE_MEASUREMENT_ID, +}; + +// Initialize firebase and mirror user to store +// eslint-disable-next-line import/prefer-default-export +export function initializeFirebase() { + firebase.initializeApp(firebaseConfig); + firebase.auth().onAuthStateChanged(user => { + store.dispatch(setAuthUser(user)); + }); +} \ No newline at end of file diff --git a/app/index.js b/app/index.js index 1631af8ff..2a9166ecc 100644 --- a/app/index.js +++ b/app/index.js @@ -3,11 +3,14 @@ import { render } from 'react-dom'; import { AppContainer } from 'react-hot-loader'; import Root from './containers/Root'; import { configureStore, history } from './store/configureStore'; +import { initializeFirebase } from './domain/FirebaseAuthentication'; import './imports.global.css'; import './app.global.scss'; export const store = configureStore(); //eslint-disable-line +initializeFirebase(); + render( diff --git a/app/reducers/auth.js b/app/reducers/auth.js new file mode 100644 index 000000000..fa318cad1 --- /dev/null +++ b/app/reducers/auth.js @@ -0,0 +1,22 @@ +import { SET_AUTH_USER } from '../actions/auth'; + +// Default state for this reducer +const defaultState = { + user: null, +}; + +export default function broadcastReducer(state = defaultState, action) { + switch (action.type) { + case SET_AUTH_USER: + return setUser(state, action); + default: + return state; + } +} + +function setUser(state, action) { + const newState = { ...state }; + const { user } = action; + newState.user = user; + return newState; +} diff --git a/app/reducers/index.js b/app/reducers/index.js index e4959420e..51536c369 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -5,6 +5,7 @@ import fileLoader from './fileLoader'; import settings from './settings'; import console from './console'; import game from './game'; +import auth from './auth'; import errors from './error'; import notifs from './notifs'; import broadcast from './broadcast'; @@ -16,6 +17,7 @@ export default function createRootReducer(history) { settings: settings, console: console, game: game, + auth: auth, errors: errors, notifs: notifs, broadcast: broadcast, diff --git a/configs/webpack.config.base.js b/configs/webpack.config.base.js index e76ea545e..c1624cc01 100644 --- a/configs/webpack.config.base.js +++ b/configs/webpack.config.base.js @@ -45,8 +45,6 @@ export default { new webpack.NamedModulesPlugin(), - new Dotenv({ - path: '../.env', - }), + new Dotenv(), ], }; From 1626177d0de2f3c10164ecbf0e7b86caf876e7c4 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 16 Sep 2020 13:54:24 +1000 Subject: [PATCH 09/87] Add loading and error state to login --- app/actions/auth.js | 42 +++++++++++++++++++++++++++++++------- app/components/Settings.js | 2 ++ app/reducers/auth.js | 22 +++++++++++++++++++- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/app/actions/auth.js b/app/actions/auth.js index ec1175c42..d10df648f 100644 --- a/app/actions/auth.js +++ b/app/actions/auth.js @@ -1,24 +1,52 @@ import { auth } from 'firebase'; export const SET_AUTH_USER = 'SET_AUTH_USER'; +export const SET_AUTH_LOADING = 'SET_AUTH_LOADING'; +export const SET_AUTH_ERROR = 'SET_AUTH_ERROR'; export function setAuthUser(user) { - return async (dispatch) => { + return async dispatch => { dispatch({ type: SET_AUTH_USER, user: user, - }) - } + }); + }; } export function login(email, password) { - return async () => { - await auth().signInWithEmailAndPassword(email, password); - } + return async (dispatch) => { + // Clear any existing errors + dispatch({ + type: SET_AUTH_ERROR, + error: null, + }); + + // Set loading state + dispatch({ + type: SET_AUTH_LOADING, + loading: true, + }); + + try { + await auth().signInWithEmailAndPassword(email, password); + } catch (err) { + console.error(err); + dispatch({ + type: SET_AUTH_ERROR, + error: err.message, + }); + } + + // Clear loading state + dispatch({ + type: SET_AUTH_LOADING, + loading: false, + }); + }; } export function logout() { return async () => { await auth().signOut(); - } + }; } diff --git a/app/components/Settings.js b/app/components/Settings.js index eede0d93f..5c5cc5987 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -136,10 +136,12 @@ export default class Settings extends Component { size="medium" basic={true} inverted={true} + disabled={auth.loading} onClick={() => this.props.login(this.state.email, this.state.password) } /> + {auth.error &&
{auth.error}
} ); } diff --git a/app/reducers/auth.js b/app/reducers/auth.js index fa318cad1..760906cb7 100644 --- a/app/reducers/auth.js +++ b/app/reducers/auth.js @@ -1,14 +1,20 @@ -import { SET_AUTH_USER } from '../actions/auth'; +import { SET_AUTH_USER, SET_AUTH_LOADING, SET_AUTH_ERROR } from '../actions/auth'; // Default state for this reducer const defaultState = { user: null, + loading: false, + error: null, }; export default function broadcastReducer(state = defaultState, action) { switch (action.type) { case SET_AUTH_USER: return setUser(state, action); + case SET_AUTH_LOADING: + return setLoading(state, action); + case SET_AUTH_ERROR: + return setError(state, action); default: return state; } @@ -20,3 +26,17 @@ function setUser(state, action) { newState.user = user; return newState; } + +function setLoading(state, action) { + const newState = { ...state }; + const { loading } = action; + newState.loading = loading; + return newState; +} + +function setError(state, action) { + const newState = { ...state }; + const { error } = action; + newState.error = error; + return newState; +} From 51ad0edf23b5bc904332be41b81007c923c49541 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 16 Sep 2020 14:08:00 +1000 Subject: [PATCH 10/87] Catch error when initializing firebase fails --- app/domain/FirebaseAuthentication.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/app/domain/FirebaseAuthentication.js b/app/domain/FirebaseAuthentication.js index f10272971..dfdc98685 100644 --- a/app/domain/FirebaseAuthentication.js +++ b/app/domain/FirebaseAuthentication.js @@ -1,7 +1,7 @@ -import firebase from "firebase"; +import firebase from 'firebase'; import { setAuthUser } from '../actions/auth'; -import { store } from "../index"; +import { store } from '../index'; const firebaseConfig = { apiKey: process.env.FIREBASE_API_KEY, @@ -17,8 +17,12 @@ const firebaseConfig = { // Initialize firebase and mirror user to store // eslint-disable-next-line import/prefer-default-export export function initializeFirebase() { - firebase.initializeApp(firebaseConfig); - firebase.auth().onAuthStateChanged(user => { - store.dispatch(setAuthUser(user)); - }); -} \ No newline at end of file + try { + firebase.initializeApp(firebaseConfig); + firebase.auth().onAuthStateChanged(user => { + store.dispatch(setAuthUser(user)); + }); + } catch (err) { + console.error("Error initializing firebase: ", err); + } +} From 0555f361fa111694786b6437395639705ac0c734 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 16 Sep 2020 14:08:34 +1000 Subject: [PATCH 11/87] Set loading state before error state --- app/actions/auth.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/actions/auth.js b/app/actions/auth.js index d10df648f..d54dead05 100644 --- a/app/actions/auth.js +++ b/app/actions/auth.js @@ -15,18 +15,18 @@ export function setAuthUser(user) { export function login(email, password) { return async (dispatch) => { - // Clear any existing errors - dispatch({ - type: SET_AUTH_ERROR, - error: null, - }); - // Set loading state dispatch({ type: SET_AUTH_LOADING, loading: true, }); + // Clear any existing errors + dispatch({ + type: SET_AUTH_ERROR, + error: null, + }); + try { await auth().signInWithEmailAndPassword(email, password); } catch (err) { From 3f7b6545b0d8c3214a44f3f6f4c603b177cdcf23 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 16 Sep 2020 14:11:11 +1000 Subject: [PATCH 12/87] Mention the .env file in firebase error message --- app/domain/FirebaseAuthentication.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/domain/FirebaseAuthentication.js b/app/domain/FirebaseAuthentication.js index dfdc98685..5bbf1175a 100644 --- a/app/domain/FirebaseAuthentication.js +++ b/app/domain/FirebaseAuthentication.js @@ -23,6 +23,6 @@ export function initializeFirebase() { store.dispatch(setAuthUser(user)); }); } catch (err) { - console.error("Error initializing firebase: ", err); + console.error("Error initializing firebase. Did you forget to create a .env file from the .env.example file?", err); } } From 4c97f629cec2a3eb099cb170b67412c2ebc698bc Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 16 Sep 2020 14:43:27 +1000 Subject: [PATCH 13/87] Move login form into a modal --- app/actions/auth.js | 7 ++-- app/components/Settings.js | 65 +++++++++++++++++++++++++++----------- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/app/actions/auth.js b/app/actions/auth.js index d54dead05..9f9c3c24f 100644 --- a/app/actions/auth.js +++ b/app/actions/auth.js @@ -13,7 +13,7 @@ export function setAuthUser(user) { }; } -export function login(email, password) { +export function login(email, password, callback) { return async (dispatch) => { // Set loading state dispatch({ @@ -28,7 +28,10 @@ export function login(email, password) { }); try { - await auth().signInWithEmailAndPassword(email, password); + const user = await auth().signInWithEmailAndPassword(email, password); + if (user && callback) { + callback(); + } } catch (err) { console.error(err); dispatch({ diff --git a/app/components/Settings.js b/app/components/Settings.js index 5c5cc5987..a25e15514 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import _ from 'lodash'; -import { Button, Message, Header, Icon, Confirm } from 'semantic-ui-react'; +import { Modal, Button, Message, Header, Icon, Confirm } from 'semantic-ui-react'; import { getDefaultDolphinPath } from '../utils/settings'; import PageHeader from './common/PageHeader'; import ActionInput from './common/ActionInput'; @@ -43,6 +43,7 @@ export default class Settings extends Component { this.state = { email: '', password: '', + showLoginModal: false, }; } @@ -103,18 +104,12 @@ export default class Settings extends Component { ); } - renderUserBlock() { + renderLoginModal() { const auth = this.props.auth || {}; - - if (!auth.user) { - return ( -
- + return ( + this.setState({showLoginModal: false})}> + Login +
this.setState({ password: e.target.value })} />
+ + {auth.error &&
{auth.error}
} +
+
+ ); + } + + handleLogin() { + const { email, password } = this.state; + this.props.login(email, password, () => { + // Clear the state on successful login + this.setState({ + email: "", + password: "", + showLoginModal: false, + }); + }); + } + + renderUserBlock() { + const auth = this.props.auth || {}; + + if (!auth.user) { + return ( + +
+ {this.renderLoginModal()} +
); } @@ -403,7 +430,7 @@ export default class Settings extends Component { renderUserAuth() { return (
-
Connect with Slippi.gg
+
Slippi.gg Integration
{this.renderUserBlock()} From 5acf90af40c2c6b2da409e99ace5bc3f120ad2dd Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 16 Sep 2020 14:49:35 +1000 Subject: [PATCH 14/87] Require user to be logged in to start broadcast --- app/components/Broadcast.js | 11 ++++++++++- app/components/Settings.js | 3 ++- app/containers/BroadcastPage.js | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 1fdd90dfb..2a162dbe5 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -25,6 +25,7 @@ export default class Broadcast extends Component { // store data history: PropTypes.object.isRequired, broadcast: PropTypes.object.isRequired, + auth: PropTypes.object.isRequired, errors: PropTypes.object.isRequired, topNotifOffset: PropTypes.number.isRequired, }; @@ -72,8 +73,16 @@ export default class Broadcast extends Component { } renderContent() { + const { user } = this.props.auth; + if (!user) { + return ( +
+

You must be logged in to broadcast

+
+ ); + } + const { slippiConnectionStatus, dolphinConnectionStatus, startTime, endTime, isConnecting, isBroadcasting } = this.props.broadcast; - console.log(JSON.stringify(this.props)); return (
{this.renderGlobalError()} diff --git a/app/components/Settings.js b/app/components/Settings.js index a25e15514..425bd5503 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -157,6 +157,7 @@ export default class Settings extends Component {
{this.renderLoginModal()} -
Slippi.gg Integration
+
Connection Settings
{this.renderUserBlock()} diff --git a/app/containers/BroadcastPage.js b/app/containers/BroadcastPage.js index e0b742bae..194538e0b 100644 --- a/app/containers/BroadcastPage.js +++ b/app/containers/BroadcastPage.js @@ -9,6 +9,7 @@ function mapStateToProps(state) { return { errors: state.errors, broadcast: state.broadcast, + auth: state.auth, topNotifOffset: _.get(state.notifs, ['activeNotif', 'heightPx']) || 0, }; } From ac00c3b513d48dd63d9efa61104a1e88167219d6 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 16 Sep 2020 14:56:52 +1000 Subject: [PATCH 15/87] Improve user not logged in landing --- app/components/Broadcast.js | 39 ++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 2a162dbe5..dfbd123c3 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -5,7 +5,11 @@ import PropTypes from 'prop-types'; import { Button, + Header, + Segment, + Icon, } from 'semantic-ui-react'; +import { Link } from 'react-router-dom'; import PageHeader from './common/PageHeader'; import PageWrapper from './PageWrapper'; @@ -72,14 +76,39 @@ export default class Broadcast extends Component { ); } + renderNotLoggedIn() { + return ( +
+
+ + + Not logged in + + You must be logged in to broadcast your gameplay. Go to the settings page to log in. + + +
+ + + + + +
+ ); + } + renderContent() { const { user } = this.props.auth; if (!user) { - return ( -
-

You must be logged in to broadcast

-
- ); + return this.renderNotLoggedIn(); } const { slippiConnectionStatus, dolphinConnectionStatus, startTime, endTime, isConnecting, isBroadcasting } = this.props.broadcast; From 4f75f8813f8d1730938b13856f1d2bed5e11f860 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 16 Sep 2020 15:00:32 +1000 Subject: [PATCH 16/87] Fix log out button styles --- app/components/Settings.js | 39 ++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/app/components/Settings.js b/app/components/Settings.js index 425bd5503..03cffa600 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -1,7 +1,14 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import _ from 'lodash'; -import { Modal, Button, Message, Header, Icon, Confirm } from 'semantic-ui-react'; +import { + Modal, + Button, + Message, + Header, + Icon, + Confirm, +} from 'semantic-ui-react'; import { getDefaultDolphinPath } from '../utils/settings'; import PageHeader from './common/PageHeader'; import ActionInput from './common/ActionInput'; @@ -107,7 +114,10 @@ export default class Settings extends Component { renderLoginModal() { const auth = this.props.auth || {}; return ( - this.setState({showLoginModal: false})}> + this.setState({ showLoginModal: false })} + > Login
@@ -129,7 +139,9 @@ export default class Settings extends Component { type="button" disabled={auth.loading} onClick={() => this.handleLogin()} - >Login + > + Login + {auth.error &&
{auth.error}
} @@ -141,8 +153,8 @@ export default class Settings extends Component { this.props.login(email, password, () => { // Clear the state on successful login this.setState({ - email: "", - password: "", + email: '', + password: '', showLoginModal: false, }); }); @@ -153,7 +165,6 @@ export default class Settings extends Component { if (!auth.user) { return ( -
{this.renderLoginModal()} this.setState({showLoginModal: true})} + onClick={() => this.setState({ showLoginModal: true })} />
); } - return

Welcome {auth.user.displayName}

; + return ( +
+

Welcome {auth.user.displayName}

+
+ ); } renderConfigDolphin() { From 43abfa24ae6528d147b332001cf29bb3f0a61f25 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 16 Sep 2020 15:25:53 +1000 Subject: [PATCH 17/87] Allow hiding and showing of the user password --- app/components/Settings.js | 65 +++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/app/components/Settings.js b/app/components/Settings.js index 03cffa600..b7ecd3a55 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -6,6 +6,7 @@ import { Button, Message, Header, + Form, Icon, Confirm, } from 'semantic-ui-react'; @@ -51,6 +52,7 @@ export default class Settings extends Component { email: '', password: '', showLoginModal: false, + showPassword: false, }; } @@ -112,36 +114,47 @@ export default class Settings extends Component { } renderLoginModal() { + const { showPassword, showLoginModal, email, password } = this.state; const auth = this.props.auth || {}; + + const togglePass = () => this.setState({ + showPassword: !showPassword, + }); + return ( this.setState({ showLoginModal: false })} > - Login + Login with Slippi.gg -
- - this.setState({ email: e.target.value })} - /> -
-
- - this.setState({ password: e.target.value })} - /> -
- +
this.handleLogin()}> +
+ + this.setState({ email: e.target.value })} + /> +
+
+ + + } + type={showPassword ? 'text' : 'password'} + value={password} + onChange={e => this.setState({ password: e.target.value })} + /> +
+ +
{auth.error &&
{auth.error}
}
@@ -170,11 +183,11 @@ export default class Settings extends Component { + ); + } + + renderChannels() { + const channels = _.get(this.props.broadcast, 'channels') || []; + const broadcastEntries = _.map(channels, channel => ( + +
{channel.id}
+ +
+ )); + + return ( +
+ {broadcastEntries} +
+ ); + } + renderNotLoggedIn() { return (
@@ -121,6 +164,9 @@ export default class Broadcast extends Component {
slippi connection status: {JSON.stringify(slippiConnectionStatus)}
isBroadcasting: {JSON.stringify(isBroadcasting)}
isConnecting: {JSON.stringify(isConnecting)}
+

Spectate

+ {this.renderRefreshButton()} + {this.renderChannels()}
); } diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index 02bc8480a..097c99f48 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -53,8 +53,6 @@ export class BroadcastManager { headers.authorization = `Bearer ${token}`; } - console.log(headers); - const socket = new WebSocketClient(); socket.on('connect', (connection) => { @@ -98,8 +96,11 @@ export class BroadcastManager { _handleGameData(data) { if (this.wsConnection) { - console.log(data); - this.wsConnection.sendUTF(JSON.stringify(data)); + const base64 = data.toString('base64'); + this.wsConnection.sendUTF(JSON.stringify({ + type: "game_event", + payload: base64, + })); } } } diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js new file mode 100644 index 000000000..2806d2671 --- /dev/null +++ b/app/domain/SpectateManager.js @@ -0,0 +1,120 @@ +import log from 'electron-log'; +import { client as WebSocketClient } from 'websocket'; +import * as firebase from 'firebase'; + +import DolphinManager from './DolphinManager'; +import SlpFileWriter from './SlpFileWriter'; +import { store } from '../index'; +import { updateBroadcastChannels } from '../actions/broadcast'; +import { displayError } from '../actions/error'; + +const SLIPPI_WS_SERVER = process.env.SLIPPI_WS_SERVER; + +/** + * Responsible for retrieving Dolphin game data over enet and sending the data + * to the Slippi server over websockets. + */ +// eslint-disable-next-line import/prefer-default-export +export class SpectateManager { + constructor() { + this.wsConnection = null; + this.channels = []; + + // A connection can mirror its received gameplay + this.dolphinManager = new DolphinManager(`spectate`, { mode: 'mirror' }); + + // Initialize SlpFileWriter for writting files + const slpSettings = { + folderPath: "C:/Users/Jas/Documents/Slippi/Spectate", + onFileStateChange: () => { }, + }; + this.slpFileWriter = new SlpFileWriter(slpSettings); + this.slpFileWriter.on("new-file", (curFilePath) => { + this.dolphinManager.playFile(curFilePath, false); + }); + } + + /** + * Connects to the Slippi server and the local Dolphin instance + */ + async connect() { + if (this.wsConnection) { + // We're already connected + console.log("Skipping websocket connection since we're already connected"); + return; + } + + const headers = {}; + const user = firebase.auth().currentUser; + if (user) { + const token = await user.getIdToken(); + headers.authorization = `Bearer ${token}`; + } + + const socket = new WebSocketClient(); + + socket.on('connect', (connection) => { + this.wsConnection = connection; + + connection.on('error', (err) => { + log.error("[BroadcastManager] Error connecting to Slippi server: ", err); + const errorAction = displayError( + 'broadcast-global', + err.message, + ); + store.dispatch(errorAction); + }); + + connection.on('close', () => { + // Clear the socket and disconnect from Dolphin too if we're still connected + this.wsConnection = null; + }); + + connection.on('message', message => { + if (message.type !== "utf8") { + return; + } + + const obj = JSON.parse(message.utf8Data); + switch (obj.type) { + case 'list-channels-resp': + this.channels = obj.channels || []; + store.dispatch(updateBroadcastChannels(this.channels)); + break; + case 'game_event': + const buf = Buffer.from(obj.payload, 'base64'); + this.slpFileWriter.handleData(buf); + break; + default: + console.log(`Ws resp type ${obj.type} not supported`); + break; + } + }); + }); + + socket.connect(SLIPPI_WS_SERVER, 'spectate-protocol', undefined, headers); + } + + refreshChannels() { + if (!this.wsConnection) { + return; + } + + this.wsConnection.sendUTF(JSON.stringify({ + type: "list-channels", + })); + } + + watchChannel(channelId) { + if (!this.wsConnection) { + return; + } + + this.wsConnection.sendUTF(JSON.stringify({ + type: "change-channel", + channelId: channelId, + })); + + this.dolphinManager.startPlayback(); + } +} \ No newline at end of file diff --git a/app/reducers/broadcast.js b/app/reducers/broadcast.js index d4387a40f..ea43b1e41 100644 --- a/app/reducers/broadcast.js +++ b/app/reducers/broadcast.js @@ -1,5 +1,5 @@ import { ConnectionStatus } from '@slippi/slippi-js'; -import { SET_DOLPHIN_STATUS, SET_SLIPPI_STATUS } from '../actions/broadcast'; +import { SET_DOLPHIN_STATUS, SET_SLIPPI_STATUS, UPDATE_BROADCAST_CHANNELS } from '../actions/broadcast'; // Default state for this reducer const defaultState = { @@ -9,6 +9,7 @@ const defaultState = { slippiConnectionStatus: ConnectionStatus.DISCONNECTED, isBroadcasting: false, isConnecting: false, + channels: [], }; export default function broadcastReducer(state = defaultState, action) { @@ -21,6 +22,8 @@ export default function broadcastReducer(state = defaultState, action) { return setDolphinStatus(state, action); case SET_SLIPPI_STATUS: return setSlippiStatus(state, action); + case UPDATE_BROADCAST_CHANNELS: + return updateBroadcastChannels(state, action); default: return state; } @@ -55,4 +58,12 @@ function updateBroadcastStatus(oldState, state) { newState.endTime = new Date(); } return newState; +} + +function updateBroadcastChannels(state, action) { + const { channels } = action; + return { + ...state, + channels: channels, + }; } \ No newline at end of file From 45324bcd2e5720861a3265ec5c7b77a11d55b248 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Sat, 19 Sep 2020 19:26:23 -0700 Subject: [PATCH 22/87] fix preload issue where path gets an undefined val --- app/main.dev.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/main.dev.js b/app/main.dev.js index 269ffbbe0..1d0669973 100644 --- a/app/main.dev.js +++ b/app/main.dev.js @@ -57,11 +57,11 @@ const handlePreloadLogic = async () => { if (isProd && (platform === "win32" || platform === "darwin" || process.env.APPIMAGE)) { log.info("Checking if Dolphin path has been moved..."); - const appPath = app.getAppPath(); + const appPath = process.env.APPDIR || app.getAppPath(); const exePlatformPaths = { "win32": path.join(appPath, "../../Slippi Launcher.exe"), "darwin": path.join(appPath, "../../MacOS/Slippi Launcher"), - "linux": path.join(process.env.APPDIR, "AppRun"), + "linux": path.join(appPath, "AppRun"), }; // If on production and mac/windows/appimage, let's see if this is a fresh install From 332003bbc8e14bad792337249268b0d539b8ffeb Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Sun, 20 Sep 2020 13:49:27 -0700 Subject: [PATCH 23/87] fix bug with loading past games --- app/domain/DolphinManager.js | 17 ++++++++++------- app/domain/SpectateManager.js | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/app/domain/DolphinManager.js b/app/domain/DolphinManager.js index 9e64539e7..4a863f4e7 100644 --- a/app/domain/DolphinManager.js +++ b/app/domain/DolphinManager.js @@ -8,14 +8,16 @@ import retry from 'async-retry'; import log from 'electron-log'; import ini from 'ini'; import electronSettings from 'electron-settings'; +import { EventEmitter } from 'events'; import { getDolphinPath } from '../utils/settings'; import { sudoRemovePath } from '../utils/sudoExec'; const { app } = require('electron').remote; -export default class DolphinManager { +export default class DolphinManager extends EventEmitter { constructor(key, settings = {}) { + super(); // The key of this dolphin manager, doesn't really do anything // atm other than get added to the commFileName this.key = key; @@ -65,12 +67,12 @@ export default class DolphinManager { let isCopySuccess = false; try { - if (platform === "win32" || platform === "darwin" || process.env.APPIMAGE){ + if (platform === "win32" || platform === "darwin" || process.env.APPIMAGE) { fs.removeSync(targetPath); fs.copySync(originalDolphinPath, targetPath); } if (process.platform === "linux") { - const linuxUserDir = path.join(os.homedir(),".config", "SlippiPlayback"); + const linuxUserDir = path.join(os.homedir(), ".config", "SlippiPlayback"); fs.removeSync(linuxUserDir); // clear the User dir on linux } isCopySuccess = true; @@ -108,14 +110,14 @@ export default class DolphinManager { dolphinPath = isDev ? "./app/dolphin-dev/windows/User" : path.join(dolphinPath, "User"); break; case "linux": - dolphinPath = path.join(os.homedir(),".config", "SlippiPlayback"); + dolphinPath = path.join(os.homedir(), ".config", "SlippiPlayback"); break; default: throw new Error("The current platform is not supported"); } try { const iniPath = path.join(dolphinPath, "Config", "Dolphin.ini"); - if (fs.existsSync(iniPath)){ + if (fs.existsSync(iniPath)) { const dolphinINI = ini.parse(fs.readFileSync(iniPath, 'utf-8')); dolphinINI.General.ISOPath0 = fileDir; const numPaths = dolphinINI.General.ISOPaths; @@ -125,7 +127,7 @@ export default class DolphinManager { } else { log.info("There isn't a User dir to write to."); const configPath = path.join(dolphinPath, "Config"); - const newINI = ini.encode({"General": {"ISOPath0": fileDir, "ISOPaths": 1}}); + const newINI = ini.encode({ "General": { "ISOPath0": fileDir, "ISOPaths": 1 } }); log.info("attempting to mkdir -p"); fs.mkdirpSync(configPath); fs.writeFileSync(iniPath, newINI); @@ -227,7 +229,7 @@ export default class DolphinManager { dolphinPath = isDev ? "./app/dolphin-dev/linux" : dolphinPath; const appImagePath = path.join(dolphinPath, "Slippi_Playback-x86_64.AppImage"); const emuPath = path.join(dolphinPath, "dolphin-emu"); - if (fs.existsSync(appImagePath)){ + if (fs.existsSync(appImagePath)) { executablePath = appImagePath; } else { executablePath = emuPath; @@ -268,6 +270,7 @@ export default class DolphinManager { // TODO: Could cause the temp directory to get cluttered this.removeCommFiles(); this.isRunning = false; + this.emit('dolphin-closed'); } } } diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index 2806d2671..15dfb62e1 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -17,11 +17,16 @@ const SLIPPI_WS_SERVER = process.env.SLIPPI_WS_SERVER; // eslint-disable-next-line import/prefer-default-export export class SpectateManager { constructor() { + this.prevChannelId = null; this.wsConnection = null; this.channels = []; // A connection can mirror its received gameplay this.dolphinManager = new DolphinManager(`spectate`, { mode: 'mirror' }); + this.dolphinManager.on('dolphin-closed', () => { + // Clear previous channel ID when Dolphin closes + this.prevChannelId = null; + }); // Initialize SlpFileWriter for writting files const slpSettings = { @@ -110,11 +115,22 @@ export class SpectateManager { return; } + if (channelId === this.prevChannelId) { + // If we have not changed channels, don't do anything. Worth noting that closing + // dolphin will count as a channel change because it resets prevChannelId + return; + } + this.wsConnection.sendUTF(JSON.stringify({ type: "change-channel", channelId: channelId, })); - this.dolphinManager.startPlayback(); + // Play an empty file such that we just launch into the waiting for game screen, this is + // used to clear out any previous file that we were reading for. The file will get updated + // by the fileWriter + this.dolphinManager.playFile("", true); + + this.prevChannelId = channelId; } } \ No newline at end of file From 965f8401128430691de95d47199c8e8b7715b5b4 Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Mon, 21 Sep 2020 14:51:07 -0700 Subject: [PATCH 24/87] change text --- app/components/Home.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/Home.js b/app/components/Home.js index 7560e3a89..51c73bcd8 100644 --- a/app/components/Home.js +++ b/app/components/Home.js @@ -133,8 +133,8 @@ export default class Home extends Component { navigationElements.push( this.generateNav( 'podcast', - 'Broadcast Gameplay', - 'Allow others to spectate your gameplay', + 'Gameplay Broadcasts', + 'Share your gameplay or watch others', '/broadcast', false ) From 3959740049fc71ee0b09a398f8429bc2920d4896 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Mon, 21 Sep 2020 12:09:15 +1000 Subject: [PATCH 25/87] Fix default port showing up as undefined --- app/components/Console.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/Console.js b/app/components/Console.js index 84bd88cb5..eaad37ec8 100644 --- a/app/components/Console.js +++ b/app/components/Console.js @@ -701,11 +701,11 @@ export default class Console extends Component {
- The connection port should only be changed if you are connecting to a relay, {Ports.WII_DEFAULT} is the port all Wiis use to send data. + The connection port should only be changed if you are connecting to a relay, {Ports.DEFAULT} is the port all Wiis use to send data.
From fd7b00d16292df99a1026f11f3872eee2170ab23 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Tue, 22 Sep 2020 19:07:25 +1000 Subject: [PATCH 26/87] Fix disconnecting from connecting console --- app/domain/SlpNetworking.js | 60 ++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/app/domain/SlpNetworking.js b/app/domain/SlpNetworking.js index 0cf709ea8..337ce54b9 100644 --- a/app/domain/SlpNetworking.js +++ b/app/domain/SlpNetworking.js @@ -21,7 +21,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import _ from 'lodash'; -import { ConsoleConnection, ConnectionStatus } from '@slippi/slippi-js'; +import { Ports, ConsoleConnection, ConnectionStatus } from '@slippi/slippi-js'; import { store } from '../index'; import { connectionStateChanged } from '../actions/console'; @@ -45,11 +45,9 @@ export default class SlpNetworking { this.isRelaying = settings.isRelaying; this.isMirroring = false; - this.connectionsByPort = []; - this.clientsByPort = []; + this.connections = []; this.connectionStatus = ConnectionStatus.DISCONNECTED; this.connDetails = this.getDefaultConnDetails(); - this.consoleConn = null; // A connection can mirror its received gameplay this.dolphinManager = new DolphinManager(`mirror-${this.id}`, { mode: 'mirror' }); @@ -116,34 +114,53 @@ export default class SlpNetworking { } connect() { + this.setStatus(ConnectionStatus.CONNECTING); // Update dolphin manager settings const connectionSettings = this.getSettings(); this.slpFileWriter.updateSettings(connectionSettings); this.slpFileWriter.connectOBS(); this.dolphinManager.updateSettings(connectionSettings); - console.log(`Connecting to: ${this.ipAdress}:${this.port}`); - if (!this.consoleConn) this.consoleConn = new ConsoleConnection(); - this.consoleConn.connect(this.ipAddress, this.port); - this.consoleConn.on("handshake", (details) => { - console.log(details); - this.connDetails = {...this.connDetails, ...details}; - console.log(this.connDetails); - }); - this.consoleConn.on("statusChange", (status) => { - this.connectionStatus = status; - this.forceConsoleUiUpdate(); + if (this.port && this.port !== Ports.LEGACY && this.port !== Ports.DEFAULT) { + // If port is manually set, use that port. Don't do this if the port is set to legacy as + // somebody might have accidentally set it to that and they would encounter issues with + // the new Nintendont + this.connectOnPort(this.port); + } else { + // Try both the default and legacy ports + this.connectOnPort(Ports.DEFAULT); + this.connectOnPort(Ports.LEGACY); + } + } + + connectOnPort(port) { + const conn = new ConsoleConnection(); + // Only add the event listeners once we've connected + conn.once("connect", () => { + conn.on("handshake", (details) => { + console.log(details); + this.connDetails = {...this.connDetails, ...details}; + console.log(this.connDetails); + }); + conn.on("statusChange", (status) => this.setStatus(status)); + conn.on("data", (data) => this.handleReplayData(data)); }); - this.consoleConn.on("data", (data) => this.handleReplayData(data)); + this.connections.push(conn); + // Actually try to connect + console.log(`Connecting to: ${this.ipAddress}:${port}`); + conn.connect(this.ipAddress, port); } disconnect() { console.log("Disconnect request"); this.slpFileWriter.disconnectOBS(); - this.consoleConn.disconnect(); + this.connections.forEach((conn) => { + conn.disconnect(); + }); + this.connections = []; - this.forceConsoleUiUpdate(); + this.setStatus(ConnectionStatus.DISCONNECTED); } handleReplayData(data) { @@ -162,4 +179,11 @@ export default class SlpNetworking { this.forceConsoleUiUpdate(); } } + + setStatus(status) { + if (this.connectionStatus !== status) { + this.connectionStatus = status; + this.forceConsoleUiUpdate(); + } + } } From 87c78571fb987b133124ac4c8a76268d77b56516 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Tue, 22 Sep 2020 19:09:49 +1000 Subject: [PATCH 27/87] Try DolphinConnection when streaming from console --- app/domain/SlpNetworking.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/domain/SlpNetworking.js b/app/domain/SlpNetworking.js index 337ce54b9..de0e15ece 100644 --- a/app/domain/SlpNetworking.js +++ b/app/domain/SlpNetworking.js @@ -21,7 +21,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import _ from 'lodash'; -import { Ports, ConsoleConnection, ConnectionStatus } from '@slippi/slippi-js'; +import { Ports, DolphinConnection, ConsoleConnection, ConnectionStatus } from '@slippi/slippi-js'; import { store } from '../index'; import { connectionStateChanged } from '../actions/console'; @@ -130,11 +130,19 @@ export default class SlpNetworking { // Try both the default and legacy ports this.connectOnPort(Ports.DEFAULT); this.connectOnPort(Ports.LEGACY); + + // Also try to connect as a Dolphin instance + this.connectOnPort(Ports.DEFAULT, "dolphin"); } } - connectOnPort(port) { - const conn = new ConsoleConnection(); + connectOnPort(port, connectionType="console") { + let conn; + if (connectionType === "console") { + conn = new ConsoleConnection(); + } else { + conn = new DolphinConnection(); + } // Only add the event listeners once we've connected conn.once("connect", () => { conn.on("handshake", (details) => { From f69416fe450c4d36b3de94fbca2a327f2f05d223 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Tue, 22 Sep 2020 19:13:21 +1000 Subject: [PATCH 28/87] Forward the raw Dolphin message to the Slippi server --- app/domain/BroadcastManager.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index 097c99f48..34d23c79d 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -27,8 +27,8 @@ export class BroadcastManager { this.stop(); } }); - this.dolphinConnection.on(ConnectionEvent.DATA, (data) => { - this._handleGameData(data); + this.dolphinConnection.on(ConnectionEvent.MESSAGE, (message) => { + this._handleGameData(message); }); } @@ -94,13 +94,9 @@ export class BroadcastManager { } } - _handleGameData(data) { + _handleGameData(message) { if (this.wsConnection) { - const base64 = data.toString('base64'); - this.wsConnection.sendUTF(JSON.stringify({ - type: "game_event", - payload: base64, - })); + this.wsConnection.sendUTF(JSON.stringify(message)); } } } From 676e59133de9f62d459c1300b0d124ec9620b22c Mon Sep 17 00:00:00 2001 From: Vince Au Date: Tue, 22 Sep 2020 20:27:54 +1000 Subject: [PATCH 29/87] Only forward the game event Dolphin messages --- app/domain/BroadcastManager.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index 34d23c79d..2af8f312f 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -4,7 +4,7 @@ import log from 'electron-log'; import { client as WebSocketClient } from 'websocket'; import * as firebase from 'firebase'; -import { DolphinConnection, Ports, ConnectionEvent, ConnectionStatus } from '@slippi/slippi-js'; +import { DolphinMessageType, DolphinConnection, Ports, ConnectionEvent, ConnectionStatus } from '@slippi/slippi-js'; import { store } from '../index'; import { setDolphinStatus, setSlippiStatus } from '../actions/broadcast'; import { displayError } from '../actions/error'; @@ -96,7 +96,10 @@ export class BroadcastManager { _handleGameData(message) { if (this.wsConnection) { - this.wsConnection.sendUTF(JSON.stringify(message)); + // Only forward the game event messages for now + if (message.type === DolphinMessageType.GAME_EVENT) { + this.wsConnection.sendUTF(JSON.stringify(message)); + } } } } From 7db85d892eda74919e07c47e78570ab023b583e0 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Tue, 22 Sep 2020 20:33:08 +1000 Subject: [PATCH 30/87] Fix error message --- app/domain/SpectateManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index 15dfb62e1..05fee9b6a 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -62,7 +62,7 @@ export class SpectateManager { this.wsConnection = connection; connection.on('error', (err) => { - log.error("[BroadcastManager] Error connecting to Slippi server: ", err); + log.error("[SpectateManager] Error connecting to Slippi server: ", err); const errorAction = displayError( 'broadcast-global', err.message, From e8ca6eb8827f048a1c94bf423a8f76f242c2834c Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Tue, 22 Sep 2020 13:13:09 -0700 Subject: [PATCH 31/87] add name to stream list --- app/components/Broadcast.js | 27 +++++++++++++++------------ app/domain/BroadcastManager.js | 1 + app/domain/SpectateManager.js | 1 + 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 2e1e6cb45..f4598b544 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -99,18 +99,21 @@ export default class Broadcast extends Component { renderChannels() { const channels = _.get(this.props.broadcast, 'channels') || []; - const broadcastEntries = _.map(channels, channel => ( - -
{channel.id}
- -
- )); + const broadcastEntries = _.map(channels, channel => { + const name = _.get(channel, ['broadcaster', 'name']); + return ( + +
{name} ({channel.id})
+ +
+ ); + }); return (
diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index 2af8f312f..f0e1f812f 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -98,6 +98,7 @@ export class BroadcastManager { if (this.wsConnection) { // Only forward the game event messages for now if (message.type === DolphinMessageType.GAME_EVENT) { + // console.log(`[Broadcaster] ${JSON.stringify(message)}`); this.wsConnection.sendUTF(JSON.stringify(message)); } } diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index 05fee9b6a..88b5e763f 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -80,6 +80,7 @@ export class SpectateManager { return; } + // console.log(`[Spectator] ${message.utf8Data}`); const obj = JSON.parse(message.utf8Data); switch (obj.type) { case 'list-channels-resp': From 28615c25e9fe1d21b7df457cc2079558a6a09250 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 30 Sep 2020 09:42:44 +1000 Subject: [PATCH 32/87] Use slippi-js@next --- package.json | 2 +- yarn.lock | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 94c06621d..0515dd389 100644 --- a/package.json +++ b/package.json @@ -255,7 +255,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^5.5.0", "@google-cloud/storage": "^2.4.2", - "@slippi/slippi-js": "^5.0.5", + "@slippi/slippi-js": "next", "async-retry": "^1.2.3", "classnames": "^2.2.6", "devtron": "^1.4.0", diff --git a/yarn.lock b/yarn.lock index bc246c0ab..e35db204b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1362,12 +1362,13 @@ array-from "^2.1.1" lodash.get "^4.4.2" -"@slippi/slippi-js@^5.0.5": - version "5.0.5" - resolved "https://registry.yarnpkg.com/@slippi/slippi-js/-/slippi-js-5.0.5.tgz#abb86b598451d100519a8cb7cddc048e58e2f9e2" - integrity sha512-iVFhJz1njibZf55KCSk8egRpuc85EnkWQtARnNLzzE6nzffMbUwZip5dHwhuH2PI8BRnPmN2M0d9Ri5QdTaZ/g== +"@slippi/slippi-js@next": + version "5.1.0-beta.0" + resolved "https://registry.yarnpkg.com/@slippi/slippi-js/-/slippi-js-5.1.0-beta.0.tgz#69ba00212866e0e45cdd71be68d5ebada2b7aa5e" + integrity sha512-Jcw0EzL+swzLqxQdt4XqUNczru7d1/pENkeCCo0/bwy1XTaKNWAptCO3rMqdY7tmRkAdu8+1H4svkEq6MD4lgQ== dependencies: "@shelacek/ubjson" "^1.0.1" + enet "^0.2.9" iconv-lite "^0.6.2" lodash "^4.17.19" moment "^2.27.0" @@ -5235,6 +5236,11 @@ endpoint-utils@^1.0.2: ip "^1.1.3" pinkie-promise "^1.0.0" +enet@^0.2.9: + version "0.2.9" + resolved "https://registry.yarnpkg.com/enet/-/enet-0.2.9.tgz#d7fd68a0bf8bb3891408ea465e26ed6955822a1a" + integrity sha1-1/1ooL+Ls4kUCOpGXibtaVWCKho= + enhanced-resolve@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" From afd1a921807839849e568e3ace9b9a4b6b801b4f Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 30 Sep 2020 10:48:59 +1000 Subject: [PATCH 33/87] Improve login dialog styles --- app/components/Settings.js | 42 ++++++++++++++++-------------------- app/components/Settings.scss | 5 +++++ 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/app/components/Settings.js b/app/components/Settings.js index b7ecd3a55..e1fb3c304 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -129,33 +129,29 @@ export default class Settings extends Component { Login with Slippi.gg
this.handleLogin()}> -
- - this.setState({ email: e.target.value })} - /> -
-
- - - } - type={showPassword ? 'text' : 'password'} - value={password} - onChange={e => this.setState({ password: e.target.value })} - /> -
+ this.setState({ email: e.target.value })} + /> + + } + type={showPassword ? 'text' : 'password'} + value={password} + onChange={e => this.setState({ password: e.target.value })} + /> + {auth.error &&
{auth.error}
} - {auth.error &&
{auth.error}
}
); diff --git a/app/components/Settings.scss b/app/components/Settings.scss index 4ceb8d905..78093edf7 100644 --- a/app/components/Settings.scss +++ b/app/components/Settings.scss @@ -65,3 +65,8 @@ color: #EED202 !important; } } + +.login-error { + color: #DB2828; + padding-bottom: 10px; +} \ No newline at end of file From 870750926f2e9b8906217c82ca1e43df58432d07 Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Fri, 2 Oct 2020 18:08:01 -0400 Subject: [PATCH 34/87] support passing password to service --- app/actions/broadcast.js | 8 +-- app/components/Broadcast.js | 96 ++++++++++++++++++++++++++++------ app/components/Broadcast.scss | 11 ++++ app/domain/BroadcastManager.js | 15 +++++- app/domain/SpectateManager.js | 17 +++++- 5 files changed, 122 insertions(+), 25 deletions(-) diff --git a/app/actions/broadcast.js b/app/actions/broadcast.js index 8e562f7c7..5baa9e49d 100644 --- a/app/actions/broadcast.js +++ b/app/actions/broadcast.js @@ -35,9 +35,9 @@ export function updateBroadcastChannels(channels) { }; } -export function startBroadcast() { +export function startBroadcast(password) { return async () => { - await broadcastManager.start(); + await broadcastManager.start(password); }; } @@ -59,8 +59,8 @@ export function watchChannel(channelId) { }; } -export function initSpectate() { +export function initSpectate(password) { return async () => { - await spectateManager.connect(); + await spectateManager.connect(password); }; } \ No newline at end of file diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index f4598b544..3388f6294 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -5,10 +5,7 @@ import PropTypes from 'prop-types'; import _ from 'lodash'; import { - Button, - Header, - Segment, - Icon, + Button, Header, Segment, Icon, Tab, Input, } from 'semantic-ui-react'; import { Link } from 'react-router-dom'; @@ -39,8 +36,8 @@ export default class Broadcast extends Component { topNotifOffset: PropTypes.number.isRequired, }; - componentDidMount() { - this.props.initSpectate(); + state = { + password: "", } renderGlobalError() { @@ -71,7 +68,7 @@ export default class Broadcast extends Component { if (active) { this.props.stopBroadcast(); } else { - this.props.startBroadcast(); + this.props.startBroadcast(this.state.password); } }; return ( @@ -151,25 +148,90 @@ export default class Broadcast extends Component { ); } + renderBroadcastContent() { + const { slippiConnectionStatus, dolphinConnectionStatus, startTime, endTime, isConnecting, isBroadcasting } = this.props.broadcast; + + return ( +
+

Broadcast

+ + {this.renderButton()} +
+
Status: {isBroadcasting ? `broadcasting since ${JSON.stringify(startTime)}` : endTime ? `broadcast lasted ${(endTime - startTime) / 1000} seconds` : "not broadcasting"}
+
dolphin connection status: {JSON.stringify(dolphinConnectionStatus)}
+
slippi connection status: {JSON.stringify(slippiConnectionStatus)}
+
isBroadcasting: {JSON.stringify(isBroadcasting)}
+
isConnecting: {JSON.stringify(isConnecting)}
+
+
+
+ ); + } + + renderSpectateContent() { + return ( +
+

Spectate

+ {this.renderRefreshButton()} + {this.renderChannels()} +
+ ); + } + + renderTabs() { + const panes = [ + { + menuItem: "Broadcast", + render: _.bind(this.renderBroadcastContent, this), + }, + { + menuItem: "Spectate", + render: _.bind(this.renderSpectateContent, this), + }, + ]; + + return ( + { + if (data.activeIndex !== 1) { + return; + } + + this.props.initSpectate(this.state.password); + }} + /> + ); + } + + renderPasswordInput() { + return ( + { + this.setState({ + password: p.value, + }); + }} + /> + ); + } + renderContent() { const { user } = this.props.auth; if (!user) { return this.renderNotLoggedIn(); } - const { slippiConnectionStatus, dolphinConnectionStatus, startTime, endTime, isConnecting, isBroadcasting } = this.props.broadcast; return (
{this.renderGlobalError()} - {this.renderButton()} -
Status: {isBroadcasting ? `broadcasting since ${JSON.stringify(startTime)}` : endTime ? `broadcast lasted ${(endTime - startTime) / 1000} seconds` : "not broadcasting"}
-
dolphin connection status: {JSON.stringify(dolphinConnectionStatus)}
-
slippi connection status: {JSON.stringify(slippiConnectionStatus)}
-
isBroadcasting: {JSON.stringify(isBroadcasting)}
-
isConnecting: {JSON.stringify(isConnecting)}
-

Spectate

- {this.renderRefreshButton()} - {this.renderChannels()} + {this.renderPasswordInput()} + {this.renderTabs()}
); } diff --git a/app/components/Broadcast.scss b/app/components/Broadcast.scss index eb631bade..a73401e15 100644 --- a/app/components/Broadcast.scss +++ b/app/components/Broadcast.scss @@ -6,6 +6,17 @@ margin-right: auto; } +.tabs { + margin-top: 24px; + + :global(.menu) { + border-color: rgba(255, 255, 255, 0.2) !important; + a { + color: $foreground !important; + } + } +} + .section { margin-bottom: 48px; } diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index f0e1f812f..b9e25b6eb 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -35,7 +35,7 @@ export class BroadcastManager { /** * Connects to the Slippi server and the local Dolphin instance */ - async start() { + async start(password) { if (this.wsConnection) { // We're already connected console.log("Skipping websocket connection since we're already connected"); @@ -46,7 +46,9 @@ export class BroadcastManager { console.log("Attempting to connect to the Slippi server"); store.dispatch(setSlippiStatus(ConnectionStatus.CONNECTING)); - const headers = {}; + const headers = { + password: password, + }; const user = firebase.auth().currentUser; if (user) { const token = await user.getIdToken(); @@ -55,6 +57,15 @@ export class BroadcastManager { const socket = new WebSocketClient(); + socket.on('connectFailed', (error) => { + store.dispatch(setSlippiStatus(ConnectionStatus.DISCONNECTED)); + const errorAction = displayError( + 'broadcast-global', + error.message, + ); + store.dispatch(errorAction); + }); + socket.on('connect', (connection) => { this.wsConnection = connection; diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index 88b5e763f..f62f4524c 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -42,14 +42,16 @@ export class SpectateManager { /** * Connects to the Slippi server and the local Dolphin instance */ - async connect() { + async connect(password) { if (this.wsConnection) { // We're already connected console.log("Skipping websocket connection since we're already connected"); return; } - const headers = {}; + const headers = { + password: password, + }; const user = firebase.auth().currentUser; if (user) { const token = await user.getIdToken(); @@ -58,6 +60,14 @@ export class SpectateManager { const socket = new WebSocketClient(); + socket.on('connectFailed', (error) => { + const errorAction = displayError( + 'broadcast-global', + error.message, + ); + store.dispatch(errorAction); + }); + socket.on('connect', (connection) => { this.wsConnection = connection; @@ -73,6 +83,9 @@ export class SpectateManager { connection.on('close', () => { // Clear the socket and disconnect from Dolphin too if we're still connected this.wsConnection = null; + + // TODO: Somehow kill dolphin? Or maybe reconnect to a person's broadcast when it + // TODO: comes back up? }); connection.on('message', message => { From a1cfb1388a6f34763d05916ee5229ab9fa60304a Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Fri, 2 Oct 2020 18:28:00 -0400 Subject: [PATCH 35/87] remove hardcoding documents path for spectating --- app/domain/SpectateManager.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index f62f4524c..a0b005ebf 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -1,6 +1,8 @@ import log from 'electron-log'; import { client as WebSocketClient } from 'websocket'; import * as firebase from 'firebase'; +import fs from 'fs-extra'; +import path from 'path'; import DolphinManager from './DolphinManager'; import SlpFileWriter from './SlpFileWriter'; @@ -8,6 +10,8 @@ import { store } from '../index'; import { updateBroadcastChannels } from '../actions/broadcast'; import { displayError } from '../actions/error'; +const { app } = require('electron').remote; + const SLIPPI_WS_SERVER = process.env.SLIPPI_WS_SERVER; /** @@ -28,9 +32,15 @@ export class SpectateManager { this.prevChannelId = null; }); + // Get path for spectate replays in my documents + const documentsPath = app.getPath("documents"); + const targetPath = path.join(documentsPath, 'Slippi', 'Spectate'); + fs.ensureDirSync(targetPath); + console.log(targetPath); + // Initialize SlpFileWriter for writting files const slpSettings = { - folderPath: "C:/Users/Jas/Documents/Slippi/Spectate", + folderPath: targetPath, onFileStateChange: () => { }, }; this.slpFileWriter = new SlpFileWriter(slpSettings); From 1dc80c147b6f2deb2db4a076de7f4c171b68c1c9 Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Fri, 2 Oct 2020 19:00:08 -0400 Subject: [PATCH 36/87] change to only connect spectator on refresh --- app/actions/broadcast.js | 15 ++++-- app/components/Broadcast.js | 10 +--- app/domain/SpectateManager.js | 98 +++++++++++++++++++---------------- 3 files changed, 65 insertions(+), 58 deletions(-) diff --git a/app/actions/broadcast.js b/app/actions/broadcast.js index 5baa9e49d..c79973b2a 100644 --- a/app/actions/broadcast.js +++ b/app/actions/broadcast.js @@ -47,9 +47,14 @@ export function stopBroadcast() { }; } -export function refreshBroadcasts() { +export function refreshBroadcasts(password) { return async () => { - spectateManager.refreshChannels(); + try { + await spectateManager.connect(password); + spectateManager.refreshChannels(); + } catch { + // Do nothing + } }; } @@ -61,6 +66,10 @@ export function watchChannel(channelId) { export function initSpectate(password) { return async () => { - await spectateManager.connect(password); + try { + await spectateManager.connect(password); + } catch { + // Do nothing + } }; } \ No newline at end of file diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 3388f6294..2d5c423e1 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -26,7 +26,6 @@ export default class Broadcast extends Component { stopBroadcast: PropTypes.func.isRequired, refreshBroadcasts: PropTypes.func.isRequired, watchChannel: PropTypes.func.isRequired, - initSpectate: PropTypes.func.isRequired, // store data history: PropTypes.object.isRequired, @@ -87,7 +86,7 @@ export default class Broadcast extends Component { @@ -195,13 +194,6 @@ export default class Broadcast extends Component { className={styles['tabs']} menu={{ secondary: true, pointing: true }} panes={panes} - onTabChange={(event, data) => { - if (data.activeIndex !== 1) { - return; - } - - this.props.initSpectate(this.state.password); - }} /> ); } diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index a0b005ebf..38f9d0ec8 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -68,60 +68,66 @@ export class SpectateManager { headers.authorization = `Bearer ${token}`; } - const socket = new WebSocketClient(); - - socket.on('connectFailed', (error) => { - const errorAction = displayError( - 'broadcast-global', - error.message, - ); - store.dispatch(errorAction); - }); - - socket.on('connect', (connection) => { - this.wsConnection = connection; - - connection.on('error', (err) => { - log.error("[SpectateManager] Error connecting to Slippi server: ", err); + await new Promise((resolve, reject) => { + const socket = new WebSocketClient(); + + socket.on('connectFailed', (error) => { const errorAction = displayError( 'broadcast-global', - err.message, + error.message, ); store.dispatch(errorAction); - }); - connection.on('close', () => { - // Clear the socket and disconnect from Dolphin too if we're still connected - this.wsConnection = null; - - // TODO: Somehow kill dolphin? Or maybe reconnect to a person's broadcast when it - // TODO: comes back up? + reject(); }); - - connection.on('message', message => { - if (message.type !== "utf8") { - return; - } - - // console.log(`[Spectator] ${message.utf8Data}`); - const obj = JSON.parse(message.utf8Data); - switch (obj.type) { - case 'list-channels-resp': - this.channels = obj.channels || []; - store.dispatch(updateBroadcastChannels(this.channels)); - break; - case 'game_event': - const buf = Buffer.from(obj.payload, 'base64'); - this.slpFileWriter.handleData(buf); - break; - default: - console.log(`Ws resp type ${obj.type} not supported`); - break; - } + + socket.on('connect', (connection) => { + this.wsConnection = connection; + + connection.on('error', (err) => { + log.error("[SpectateManager] Error connecting to Slippi server: ", err); + const errorAction = displayError( + 'broadcast-global', + err.message, + ); + store.dispatch(errorAction); + }); + + connection.on('close', () => { + // Clear the socket and disconnect from Dolphin too if we're still connected + this.wsConnection = null; + + // TODO: Somehow kill dolphin? Or maybe reconnect to a person's broadcast when it + // TODO: comes back up? + }); + + connection.on('message', message => { + if (message.type !== "utf8") { + return; + } + + // console.log(`[Spectator] ${message.utf8Data}`); + const obj = JSON.parse(message.utf8Data); + switch (obj.type) { + case 'list-channels-resp': + this.channels = obj.channels || []; + store.dispatch(updateBroadcastChannels(this.channels)); + break; + case 'game_event': + const buf = Buffer.from(obj.payload, 'base64'); + this.slpFileWriter.handleData(buf); + break; + default: + console.log(`Ws resp type ${obj.type} not supported`); + break; + } + }); + + resolve(); }); + + socket.connect(SLIPPI_WS_SERVER, 'spectate-protocol', undefined, headers); }); - - socket.connect(SLIPPI_WS_SERVER, 'spectate-protocol', undefined, headers); } refreshChannels() { From 2a96fea03ca961db6f1c5fc82dec92554dc8ef0e Mon Sep 17 00:00:00 2001 From: Vince Au Date: Tue, 6 Oct 2020 15:14:25 +1100 Subject: [PATCH 37/87] Support start_game and end_game events in spectator mode --- app/domain/BroadcastManager.js | 13 +++++++++---- app/domain/SpectateManager.js | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index b9e25b6eb..1d5388944 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -4,7 +4,7 @@ import log from 'electron-log'; import { client as WebSocketClient } from 'websocket'; import * as firebase from 'firebase'; -import { DolphinMessageType, DolphinConnection, Ports, ConnectionEvent, ConnectionStatus } from '@slippi/slippi-js'; +import { DolphinConnection, Ports, ConnectionEvent, ConnectionStatus } from '@slippi/slippi-js'; import { store } from '../index'; import { setDolphinStatus, setSlippiStatus } from '../actions/broadcast'; import { displayError } from '../actions/error'; @@ -107,10 +107,15 @@ export class BroadcastManager { _handleGameData(message) { if (this.wsConnection) { - // Only forward the game event messages for now - if (message.type === DolphinMessageType.GAME_EVENT) { - // console.log(`[Broadcaster] ${JSON.stringify(message)}`); + switch (message.type) { + // Only forward these message types to the server + case "start_game": + case "game_event": + case "end_game": this.wsConnection.sendUTF(JSON.stringify(message)); + break; + default: + break; } } } diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index 38f9d0ec8..2d34491fc 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -24,6 +24,7 @@ export class SpectateManager { this.prevChannelId = null; this.wsConnection = null; this.channels = []; + this.gameStarted = false; // A connection can mirror its received gameplay this.dolphinManager = new DolphinManager(`spectate`, { mode: 'mirror' }); @@ -113,9 +114,18 @@ export class SpectateManager { this.channels = obj.channels || []; store.dispatch(updateBroadcastChannels(this.channels)); break; + case 'start_game': + this.gameStarted = true; + break; + case 'end_game': + this.gameStarted = false; + break; case 'game_event': - const buf = Buffer.from(obj.payload, 'base64'); - this.slpFileWriter.handleData(buf); + // Only forward data to the file writer when it's a new game + if (this.gameStarted) { + const buf = Buffer.from(obj.payload, 'base64'); + this.slpFileWriter.handleData(buf); + } break; default: console.log(`Ws resp type ${obj.type} not supported`); From af85a8f3ccacbc0ba7fa2a298868f5218df24839 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Tue, 6 Oct 2020 15:22:32 +1100 Subject: [PATCH 38/87] Stop receiving spectator data when dolphin is closed --- app/domain/SpectateManager.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index 2d34491fc..9b98684db 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -31,6 +31,8 @@ export class SpectateManager { this.dolphinManager.on('dolphin-closed', () => { // Clear previous channel ID when Dolphin closes this.prevChannelId = null; + // Stop receiving data from the server + this.wsConnection.close(); }); // Get path for spectate replays in my documents From f16f552ae9f3ac1e37c5f7b3572c9f8ec3d9579f Mon Sep 17 00:00:00 2001 From: Vince Au Date: Tue, 6 Oct 2020 18:08:45 +1100 Subject: [PATCH 39/87] Force end the game when we get a end_game event --- app/domain/SlpFileWriter.js | 4 ++++ app/domain/SpectateManager.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/app/domain/SlpFileWriter.js b/app/domain/SlpFileWriter.js index 59e639453..59f367ee7 100644 --- a/app/domain/SlpFileWriter.js +++ b/app/domain/SlpFileWriter.js @@ -162,6 +162,10 @@ export default class SlpFileWriter extends EventEmitter { }); } + endGame() { + this.slpStream.endCurrentFile(); + } + initializeNewGame(filePath) { const clearFileObj = this.getClearedCurrentFile(); this.currentFile = { diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index 9b98684db..caa74a35f 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -29,6 +29,8 @@ export class SpectateManager { // A connection can mirror its received gameplay this.dolphinManager = new DolphinManager(`spectate`, { mode: 'mirror' }); this.dolphinManager.on('dolphin-closed', () => { + // Reset the game started flag + this.gameStarted = false; // Clear previous channel ID when Dolphin closes this.prevChannelId = null; // Stop receiving data from the server @@ -120,6 +122,8 @@ export class SpectateManager { this.gameStarted = true; break; case 'end_game': + // End the current game if it's not already ended + this.slpFileWriter.endGame(); this.gameStarted = false; break; case 'game_event': From d87b82c4dad2aecaa8fde22bbbf647cc9ea5dac3 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Tue, 6 Oct 2020 23:26:52 +1100 Subject: [PATCH 40/87] Update @slippi/slippi-js --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 0515dd389..1b50bef20 100644 --- a/package.json +++ b/package.json @@ -255,7 +255,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^5.5.0", "@google-cloud/storage": "^2.4.2", - "@slippi/slippi-js": "next", + "@slippi/slippi-js": "^5.1.0-beta.1", "async-retry": "^1.2.3", "classnames": "^2.2.6", "devtron": "^1.4.0", diff --git a/yarn.lock b/yarn.lock index e35db204b..a9937fefa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1362,10 +1362,10 @@ array-from "^2.1.1" lodash.get "^4.4.2" -"@slippi/slippi-js@next": - version "5.1.0-beta.0" - resolved "https://registry.yarnpkg.com/@slippi/slippi-js/-/slippi-js-5.1.0-beta.0.tgz#69ba00212866e0e45cdd71be68d5ebada2b7aa5e" - integrity sha512-Jcw0EzL+swzLqxQdt4XqUNczru7d1/pENkeCCo0/bwy1XTaKNWAptCO3rMqdY7tmRkAdu8+1H4svkEq6MD4lgQ== +"@slippi/slippi-js@^5.1.0-beta.1": + version "5.1.0-beta.1" + resolved "https://registry.yarnpkg.com/@slippi/slippi-js/-/slippi-js-5.1.0-beta.1.tgz#301c49cb4ddab7e4a99c907704ef9862e86abe6d" + integrity sha512-ufgvko1HcrzsPemTeYCwHaN8Q0HsZUz/Ua1GqMUiW9lLjs5DaEsAMNnoiqzTeof+IeswnK4OJOryRezGLbGr7Q== dependencies: "@shelacek/ubjson" "^1.0.1" enet "^0.2.9" From 5cf8728f393df0cbf0ce4b62c5a5c54a45812f2b Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Tue, 6 Oct 2020 13:32:31 -0400 Subject: [PATCH 41/87] support game started logic using payload data --- app/domain/BroadcastManager.js | 9 +++++++++ app/domain/SpectateManager.js | 22 +++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index 1d5388944..207c77c71 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -112,6 +112,15 @@ export class BroadcastManager { case "start_game": case "game_event": case "end_game": + // const payloadStart = obj.payload.substring(0, 4); + // const buf = Buffer.from(payloadStart, 'base64'); + // const command = buf[0]; + // if (command) { + // console.log(`[Broadcast] Sending 0x${command.toString(16)}`); + // } else { + // console.log(`[Broadcast] Empty message received? ${JSON.stringify(message)}`); + // } + this.wsConnection.sendUTF(JSON.stringify(message)); break; default: diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index caa74a35f..5cb71f800 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -127,11 +127,31 @@ export class SpectateManager { this.gameStarted = false; break; case 'game_event': - // Only forward data to the file writer when it's a new game + const payloadStart = obj.payload.substring(0, 4); + const payloadStartBuf = Buffer.from(payloadStart, 'base64'); + const command = payloadStartBuf[0]; + if (command === 0x35) { + this.gameStarted = true; + } + + // Only forward data to the file writer when it's an active game if (this.gameStarted) { const buf = Buffer.from(obj.payload, 'base64'); this.slpFileWriter.handleData(buf); } + + if (command === 0x39) { + // End the current game if it's not already ended + this.slpFileWriter.endGame(); + this.gameStarted = false; + } + + // if (command) { + // console.log(`[Spectate] Receiving 0x${command.toString(16)}`); + // } else { + // console.log(`[Broadcast] Empty message received? ${JSON.stringify(obj)}`); + // } + break; default: console.log(`Ws resp type ${obj.type} not supported`); From 86db7b5395d7736314ac9d0399c076b9d1d09956 Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Tue, 6 Oct 2020 14:30:21 -0400 Subject: [PATCH 42/87] don't close ws connection on dolphin close this connection stays alive and is re-used for refreshes and channel changes. by closing it here, you make it impossible to watch a new channel without first refreshing (which is what triggers the connection to connect) we would need a function to unwatch the channel maybe? --- app/domain/SpectateManager.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index 5cb71f800..d38616361 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -33,8 +33,6 @@ export class SpectateManager { this.gameStarted = false; // Clear previous channel ID when Dolphin closes this.prevChannelId = null; - // Stop receiving data from the server - this.wsConnection.close(); }); // Get path for spectate replays in my documents @@ -132,10 +130,17 @@ export class SpectateManager { const command = payloadStartBuf[0]; if (command === 0x35) { this.gameStarted = true; + // console.log("[Spectate] Game start"); } // Only forward data to the file writer when it's an active game if (this.gameStarted) { + // if (command) { + // console.log(`[Spectate] Handling 0x${command.toString(16)}`); + // } else { + // console.log(`[Spectate] Empty message received? ${JSON.stringify(obj)}`); + // } + const buf = Buffer.from(obj.payload, 'base64'); this.slpFileWriter.handleData(buf); } @@ -144,13 +149,8 @@ export class SpectateManager { // End the current game if it's not already ended this.slpFileWriter.endGame(); this.gameStarted = false; + // console.log("[Spectate] Game end"); } - - // if (command) { - // console.log(`[Spectate] Receiving 0x${command.toString(16)}`); - // } else { - // console.log(`[Broadcast] Empty message received? ${JSON.stringify(obj)}`); - // } break; default: From 2eb71881a8bb7523d4b7b668b14348cda069aabd Mon Sep 17 00:00:00 2001 From: Vince Au Date: Wed, 7 Oct 2020 10:31:54 +1100 Subject: [PATCH 43/87] Add logging of Dolphin connection errors --- app/domain/BroadcastManager.js | 4 ++++ package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index 207c77c71..20adf5cc8 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -30,6 +30,10 @@ export class BroadcastManager { this.dolphinConnection.on(ConnectionEvent.MESSAGE, (message) => { this._handleGameData(message); }); + this.dolphinConnection.on(ConnectionEvent.ERROR, (err) => { + // Log the error messages we get from Dolphin + log.error(err); + }); } /** diff --git a/package.json b/package.json index 1b50bef20..b5b6957db 100644 --- a/package.json +++ b/package.json @@ -255,7 +255,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^5.5.0", "@google-cloud/storage": "^2.4.2", - "@slippi/slippi-js": "^5.1.0-beta.1", + "@slippi/slippi-js": "^5.1.0-beta.2", "async-retry": "^1.2.3", "classnames": "^2.2.6", "devtron": "^1.4.0", diff --git a/yarn.lock b/yarn.lock index a9937fefa..4abd63c0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1362,10 +1362,10 @@ array-from "^2.1.1" lodash.get "^4.4.2" -"@slippi/slippi-js@^5.1.0-beta.1": - version "5.1.0-beta.1" - resolved "https://registry.yarnpkg.com/@slippi/slippi-js/-/slippi-js-5.1.0-beta.1.tgz#301c49cb4ddab7e4a99c907704ef9862e86abe6d" - integrity sha512-ufgvko1HcrzsPemTeYCwHaN8Q0HsZUz/Ua1GqMUiW9lLjs5DaEsAMNnoiqzTeof+IeswnK4OJOryRezGLbGr7Q== +"@slippi/slippi-js@^5.1.0-beta.2": + version "5.1.0-beta.2" + resolved "https://registry.yarnpkg.com/@slippi/slippi-js/-/slippi-js-5.1.0-beta.2.tgz#e8f9ac50f97692d047a884ab73c2b3aff5873f75" + integrity sha512-OACCMaQ/gJROMuMRV2OHSHm76xUJ1mwuZw9sTDFj+Bt3ykex9IQ/3ebZ1qX7i2nWeonB/iDrigvPTTzkjL4q8w== dependencies: "@shelacek/ubjson" "^1.0.1" enet "^0.2.9" From 515eaf975be1fc33c53d2ca2b7b24959fe8797d0 Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Tue, 6 Oct 2020 19:56:07 -0400 Subject: [PATCH 44/87] add a bit of logging for now --- app/domain/SpectateManager.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index d38616361..8b16b2d60 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -29,6 +29,7 @@ export class SpectateManager { // A connection can mirror its received gameplay this.dolphinManager = new DolphinManager(`spectate`, { mode: 'mirror' }); this.dolphinManager.on('dolphin-closed', () => { + console.log("[Spectator] dolphin closed"); // Reset the game started flag this.gameStarted = false; // Clear previous channel ID when Dolphin closes @@ -97,6 +98,7 @@ export class SpectateManager { }); connection.on('close', () => { + console.log("[Spectator] connection close"); // Clear the socket and disconnect from Dolphin too if we're still connected this.wsConnection = null; From b70f9ea396d6bd70d212587cca2dbac87f46991f Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Thu, 15 Oct 2020 20:18:22 -0700 Subject: [PATCH 45/87] support latest broadcasting service version --- app/actions/broadcast.js | 14 +-- app/components/Broadcast.js | 18 ++-- app/domain/BroadcastManager.js | 154 +++++++++++++++++++++------ app/domain/SpectateManager.js | 185 +++++++++++++++++++++------------ app/reducers/broadcast.js | 14 +-- package.json | 4 +- 6 files changed, 264 insertions(+), 125 deletions(-) diff --git a/app/actions/broadcast.js b/app/actions/broadcast.js index c79973b2a..dd5027b66 100644 --- a/app/actions/broadcast.js +++ b/app/actions/broadcast.js @@ -3,7 +3,7 @@ import { SpectateManager } from '../domain/SpectateManager'; export const SET_DOLPHIN_STATUS = 'SET_DOLPHIN_STATUS'; export const SET_SLIPPI_STATUS = 'SET_SLIPPI_STATUS'; -export const UPDATE_BROADCAST_CHANNELS = 'UPDATE_BROADCAST_CHANNELS'; +export const UPDATE_VIEWABLE_BROADCASTS = 'UPDATE_VIEWABLE_BROADCASTS'; const broadcastManager = new BroadcastManager(); const spectateManager = new SpectateManager(); @@ -26,11 +26,11 @@ export function setSlippiStatus(status) { }; } -export function updateBroadcastChannels(channels) { +export function updateViewableBroadcasts(broadcasts) { return async (dispatch) => { dispatch({ - type: UPDATE_BROADCAST_CHANNELS, - channels: channels, + type: UPDATE_VIEWABLE_BROADCASTS, + broadcasts: broadcasts, }); }; } @@ -51,16 +51,16 @@ export function refreshBroadcasts(password) { return async () => { try { await spectateManager.connect(password); - spectateManager.refreshChannels(); + spectateManager.refreshBroadcasts(); } catch { // Do nothing } }; } -export function watchChannel(channelId) { +export function watchBroadcast(broadcastId) { return async () => { - spectateManager.watchChannel(channelId); + spectateManager.watchBroadcast(broadcastId); }; } diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 2d5c423e1..824b3f25e 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -25,7 +25,7 @@ export default class Broadcast extends Component { startBroadcast: PropTypes.func.isRequired, stopBroadcast: PropTypes.func.isRequired, refreshBroadcasts: PropTypes.func.isRequired, - watchChannel: PropTypes.func.isRequired, + watchBroadcast: PropTypes.func.isRequired, // store data history: PropTypes.object.isRequired, @@ -93,17 +93,17 @@ export default class Broadcast extends Component { ); } - renderChannels() { - const channels = _.get(this.props.broadcast, 'channels') || []; - const broadcastEntries = _.map(channels, channel => { - const name = _.get(channel, ['broadcaster', 'name']); + renderBroadcasts() { + const broadcasts = _.get(this.props.broadcast, 'broadcasts') || []; + const broadcastEntries = _.map(broadcasts, broadcast => { + const name = _.get(broadcast, ['broadcaster', 'name']); return ( - -
{name} ({channel.id})
+ +
{name} ({broadcast.id})
@@ -172,7 +172,7 @@ export default class Broadcast extends Component {

Spectate

{this.renderRefreshButton()} - {this.renderChannels()} + {this.renderBroadcasts()}
); } diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index 20adf5cc8..b8ea21b10 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -2,6 +2,7 @@ import log from 'electron-log'; import { client as WebSocketClient } from 'websocket'; +import _ from 'lodash'; import * as firebase from 'firebase'; import { DolphinConnection, Ports, ConnectionEvent, ConnectionStatus } from '@slippi/slippi-js'; @@ -18,9 +19,11 @@ const SLIPPI_WS_SERVER = process.env.SLIPPI_WS_SERVER; // eslint-disable-next-line import/prefer-default-export export class BroadcastManager { constructor() { + this.broadcastId = null; this.wsConnection = null; this.dolphinConnection = new DolphinConnection(); this.dolphinConnection.on(ConnectionEvent.STATUS_CHANGE, status => { + log.info(`[Broadcast] Dolphin status change: ${status}`); store.dispatch(setDolphinStatus(status)); // Disconnect from Slippi server when we disconnect from Dolphin if (status === ConnectionStatus.DISCONNECTED) { @@ -32,7 +35,16 @@ export class BroadcastManager { }); this.dolphinConnection.on(ConnectionEvent.ERROR, (err) => { // Log the error messages we get from Dolphin - log.error(err); + log.error("[Broadcast] Dolphin connection error\n", err); + }); + + this._debouncedGameDataLog = _.debounce((cursor, cmd) => { + // I can't figure out how to differentiate when an invocation is triggered by a leading vs + // falling edge, would be useful to log that + log.info(`[Broadcast] Game events edge. ${cursor} 0x${cmd ? cmd.toString(16) : "??"}`); + }, 1000, { + leading: true, + trailing: true, }); } @@ -42,12 +54,10 @@ export class BroadcastManager { async start(password) { if (this.wsConnection) { // We're already connected - console.log("Skipping websocket connection since we're already connected"); return; } // Indicate we're connecting to the Slippi server - console.log("Attempting to connect to the Slippi server"); store.dispatch(setSlippiStatus(ConnectionStatus.CONNECTING)); const headers = { @@ -59,22 +69,46 @@ export class BroadcastManager { headers.authorization = `Bearer ${token}`; } - const socket = new WebSocketClient(); + // Disable nagle because we send a lot of small packets, latency not overly important + const socket = new WebSocketClient({ + disableNagleAlgorithm: false, + }); socket.on('connectFailed', (error) => { + log.error("[Broadcast] WS failed to connect\n", error); + + const label = "x-websocket-reject-reason: "; + let message = error.message; + const pos = error.message.indexOf(label); + if (pos >= 0) { + const endPos = error.message.indexOf("\n", pos + label.length); + message = message.substring(pos + label.length, endPos >= 0 ? endPos : undefined); + } + store.dispatch(setSlippiStatus(ConnectionStatus.DISCONNECTED)); const errorAction = displayError( 'broadcast-global', - error.message, + message, ); store.dispatch(errorAction); }); socket.on('connect', (connection) => { + log.info("[Broadcast] WS connection successful"); + this.wsConnection = connection; - // We successfully connected to the Slippi server - store.dispatch(setSlippiStatus(ConnectionStatus.CONNECTED)); + const getBroadcasts = async () => { + connection.sendUTF(JSON.stringify({ + type: "get-broadcasts", + })); + }; + + const startBroadcast = async () => { + connection.sendUTF(JSON.stringify({ + type: "start-broadcast", + })); + }; // Now try connect to our local Dolphin instance this.dolphinConnection.connect( @@ -83,7 +117,7 @@ export class BroadcastManager { ); connection.on('error', (err) => { - log.error("[BroadcastManager] Error connecting to Slippi server: ", err); + log.error("[Broadcast] WS connection error encountered\n", err); const errorAction = displayError( 'broadcast-global', err.message, @@ -91,45 +125,101 @@ export class BroadcastManager { store.dispatch(errorAction); }); - connection.on('close', () => { + connection.on('close', (code, reason) => { + log.info(`[Broadcast] WS connection closed: ${code}, ${reason}`); store.dispatch(setSlippiStatus(ConnectionStatus.DISCONNECTED)); // Clear the socket and disconnect from Dolphin too if we're still connected this.wsConnection = null; + this.broadcastId = null; this.dolphinConnection.disconnect(); }); + + connection.on('message', message => { + if (message.type !== "utf8") { + return; + } + + const obj = JSON.parse(message.utf8Data); + switch (obj.type) { + case 'start-broadcast-resp': + this.broadcastId = obj.broadcastId; + store.dispatch(setSlippiStatus(ConnectionStatus.CONNECTED)); + break; + case 'get-broadcasts-resp': + const broadcasts = obj.broadcasts || []; + + if (broadcasts.length > 0) { + const broadcast = broadcasts[0]; + this.broadcastId = broadcast.id; + store.dispatch(setSlippiStatus(ConnectionStatus.CONNECTED)); + return; + } + + startBroadcast(); + break; + default: + log.error(`[Broadcast] Ws resp type ${obj.type} not supported`); + break; + } + }); + + getBroadcasts(); }); + log.info("[Broadcast] Connecting to WS service"); socket.connect(SLIPPI_WS_SERVER, 'broadcast-protocol', undefined, headers); } stop() { - if (this.wsConnection) { - this.wsConnection.close(); + if (!this.broadcastId || !this.wsConnection) { + return; } + + this.wsConnection.sendUTF(JSON.stringify({ + type: 'stop-broadcast', + broadcastId: this.broadcastId, + })); + + this.wsConnection.close(); } - _handleGameData(message) { - if (this.wsConnection) { - switch (message.type) { - // Only forward these message types to the server - case "start_game": - case "game_event": - case "end_game": - // const payloadStart = obj.payload.substring(0, 4); - // const buf = Buffer.from(payloadStart, 'base64'); - // const command = buf[0]; - // if (command) { - // console.log(`[Broadcast] Sending 0x${command.toString(16)}`); - // } else { - // console.log(`[Broadcast] Empty message received? ${JSON.stringify(message)}`); - // } - - this.wsConnection.sendUTF(JSON.stringify(message)); - break; - default: - break; - } + _handleGameData(event) { + if (!this.broadcastId || !this.wsConnection) { + return; + } + + switch (event.type) { + // Only forward these message types to the server + case "start_game": + case "game_event": + case "end_game": + const payloadStart = event.payload.substring(0, 4); + const buf = Buffer.from(payloadStart, 'base64'); + const command = buf[0]; + // if (command) { + // console.log(`[Broadcast] Sending 0x${command.toString(16)}`); + // } else { + // console.log(`[Broadcast] Empty event received? ${JSON.stringify(event)}`); + // } + + const message = { + type: 'send-event', + broadcastId: this.broadcastId, + event: event, + }; + + this.wsConnection.sendUTF(JSON.stringify(message), err => { + if (err) { + log.error("[Broadcast] WS send error encountered\n", err); + return; + } + + this._debouncedGameDataLog(event.cursor, command); + }); + break; + default: + break; } } } diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index 8b16b2d60..9900cbb76 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -1,13 +1,16 @@ +/* eslint-disable no-underscore-dangle */ + import log from 'electron-log'; import { client as WebSocketClient } from 'websocket'; import * as firebase from 'firebase'; +import _ from 'lodash'; import fs from 'fs-extra'; import path from 'path'; import DolphinManager from './DolphinManager'; import SlpFileWriter from './SlpFileWriter'; import { store } from '../index'; -import { updateBroadcastChannels } from '../actions/broadcast'; +import { updateViewableBroadcasts } from '../actions/broadcast'; import { displayError } from '../actions/error'; const { app } = require('electron').remote; @@ -21,26 +24,34 @@ const SLIPPI_WS_SERVER = process.env.SLIPPI_WS_SERVER; // eslint-disable-next-line import/prefer-default-export export class SpectateManager { constructor() { - this.prevChannelId = null; + this.prevBroadcastId = null; this.wsConnection = null; - this.channels = []; + this.broadcasts = []; this.gameStarted = false; // A connection can mirror its received gameplay this.dolphinManager = new DolphinManager(`spectate`, { mode: 'mirror' }); this.dolphinManager.on('dolphin-closed', () => { - console.log("[Spectator] dolphin closed"); + log.info("[Spectator] dolphin closed"); + + // Stop watching channel + if (this.prevBroadcastId) { + this.wsConnection.sendUTF(JSON.stringify({ + type: "close-broadcast", + broadcastId: this.prevBroadcastId, + })); + } + // Reset the game started flag this.gameStarted = false; - // Clear previous channel ID when Dolphin closes - this.prevChannelId = null; + // Clear previous broadcast ID when Dolphin closes + this.prevBroadcastId = null; }); // Get path for spectate replays in my documents const documentsPath = app.getPath("documents"); const targetPath = path.join(documentsPath, 'Slippi', 'Spectate'); fs.ensureDirSync(targetPath); - console.log(targetPath); // Initialize SlpFileWriter for writting files const slpSettings = { @@ -51,6 +62,67 @@ export class SpectateManager { this.slpFileWriter.on("new-file", (curFilePath) => { this.dolphinManager.playFile(curFilePath, false); }); + + this.debouncedGameDataLog = _.debounce((cursor, cmd) => { + // I can't figure out how to differentiate when an invocation is triggered by a leading vs + // falling edge, would be useful to log that + log.info(`[Spectate] Game events edge. ${cursor} 0x${cmd ? cmd.toString(16) : "??"}`); + }, 1000, { + leading: true, + trailing: true, + }); + } + + handleEvents(obj) { + const events = obj.events || []; + + events.forEach(event => { + switch (event.type) { + case 'start_game': + this.gameStarted = true; + break; + case 'end_game': + // End the current game if it's not already ended + this.slpFileWriter.endGame(); + this.gameStarted = false; + break; + case 'game_event': + const payloadStart = event.payload.substring(0, 4); + const payloadStartBuf = Buffer.from(payloadStart, 'base64'); + const command = payloadStartBuf[0]; + + this.debouncedGameDataLog(event.cursor, command); + + if (command === 0x35) { + this.gameStarted = true; + // console.log("[Spectate] Game start"); + } + + // Only forward data to the file writer when it's an active game + if (this.gameStarted) { + // if (command) { + // console.log(`[Spectate] Handling 0x${command.toString(16)}`); + // } else { + // console.log(`[Spectate] Empty message received? ${JSON.stringify(obj)}`); + // } + + const buf = Buffer.from(event.payload, 'base64'); + this.slpFileWriter.handleData(buf); + } + + if (command === 0x39) { + // End the current game if it's not already ended + this.slpFileWriter.endGame(); + this.gameStarted = false; + // console.log("[Spectate] Game end"); + } + + break; + default: + log.error(`[Spectate] Event type ${event.type} not supported`); + break; + } + }); } /** @@ -74,8 +146,9 @@ export class SpectateManager { await new Promise((resolve, reject) => { const socket = new WebSocketClient(); - + socket.on('connectFailed', (error) => { + log.error(`[Spectate] WS connection failed\n`, error); const errorAction = displayError( 'broadcast-global', error.message, @@ -84,114 +157,88 @@ export class SpectateManager { reject(); }); - + socket.on('connect', (connection) => { + log.info("[Spectate] WS connection successful"); this.wsConnection = connection; - + connection.on('error', (err) => { - log.error("[SpectateManager] Error connecting to Slippi server: ", err); + log.error("[Spectate] Error with WS connection\n", err); const errorAction = displayError( 'broadcast-global', err.message, ); store.dispatch(errorAction); }); - - connection.on('close', () => { - console.log("[Spectator] connection close"); + + connection.on('close', (code, reason) => { + log.info(`[Spectate] connection close: ${code}, ${reason}`); // Clear the socket and disconnect from Dolphin too if we're still connected this.wsConnection = null; - + // TODO: Somehow kill dolphin? Or maybe reconnect to a person's broadcast when it // TODO: comes back up? }); - + connection.on('message', message => { if (message.type !== "utf8") { return; } - + // console.log(`[Spectator] ${message.utf8Data}`); const obj = JSON.parse(message.utf8Data); switch (obj.type) { - case 'list-channels-resp': - this.channels = obj.channels || []; - store.dispatch(updateBroadcastChannels(this.channels)); - break; - case 'start_game': - this.gameStarted = true; + case 'list-broadcasts-resp': + this.broadcasts = obj.broadcasts || []; + store.dispatch(updateViewableBroadcasts(this.broadcasts)); break; - case 'end_game': - // End the current game if it's not already ended - this.slpFileWriter.endGame(); - this.gameStarted = false; - break; - case 'game_event': - const payloadStart = obj.payload.substring(0, 4); - const payloadStartBuf = Buffer.from(payloadStart, 'base64'); - const command = payloadStartBuf[0]; - if (command === 0x35) { - this.gameStarted = true; - // console.log("[Spectate] Game start"); - } - - // Only forward data to the file writer when it's an active game - if (this.gameStarted) { - // if (command) { - // console.log(`[Spectate] Handling 0x${command.toString(16)}`); - // } else { - // console.log(`[Spectate] Empty message received? ${JSON.stringify(obj)}`); - // } - - const buf = Buffer.from(obj.payload, 'base64'); - this.slpFileWriter.handleData(buf); - } - - if (command === 0x39) { - // End the current game if it's not already ended - this.slpFileWriter.endGame(); - this.gameStarted = false; - // console.log("[Spectate] Game end"); - } - + case 'events': + this.handleEvents(obj); break; default: - console.log(`Ws resp type ${obj.type} not supported`); + log.error(`[Spectate] Ws resp type ${obj.type} not supported`); break; } }); resolve(); }); - + socket.connect(SLIPPI_WS_SERVER, 'spectate-protocol', undefined, headers); }); } - refreshChannels() { + refreshBroadcasts() { if (!this.wsConnection) { return; } this.wsConnection.sendUTF(JSON.stringify({ - type: "list-channels", + type: "list-broadcasts", })); } - watchChannel(channelId) { + watchBroadcast(broadcastId) { if (!this.wsConnection) { return; } - if (channelId === this.prevChannelId) { - // If we have not changed channels, don't do anything. Worth noting that closing - // dolphin will count as a channel change because it resets prevChannelId + if (broadcastId === this.prevBroadcastId) { + // If we have not changed broadcasts, don't do anything. Worth noting that closing + // dolphin will count as a broadcast change because it resets prevBroadcastId return; } + if (this.prevBroadcastId) { + this.wsConnection.sendUTF(JSON.stringify({ + type: "close-broadcast", + broadcastId: this.prevBroadcastId, + })); + } + this.wsConnection.sendUTF(JSON.stringify({ - type: "change-channel", - channelId: channelId, + type: "watch-broadcast", + broadcastId: broadcastId, })); // Play an empty file such that we just launch into the waiting for game screen, this is @@ -199,6 +246,8 @@ export class SpectateManager { // by the fileWriter this.dolphinManager.playFile("", true); - this.prevChannelId = channelId; + this.prevBroadcastId = broadcastId; } -} \ No newline at end of file +} + +/* eslint-enable no-underscore-dangle */ \ No newline at end of file diff --git a/app/reducers/broadcast.js b/app/reducers/broadcast.js index ea43b1e41..ab26afd0b 100644 --- a/app/reducers/broadcast.js +++ b/app/reducers/broadcast.js @@ -1,5 +1,5 @@ import { ConnectionStatus } from '@slippi/slippi-js'; -import { SET_DOLPHIN_STATUS, SET_SLIPPI_STATUS, UPDATE_BROADCAST_CHANNELS } from '../actions/broadcast'; +import { SET_DOLPHIN_STATUS, SET_SLIPPI_STATUS, UPDATE_VIEWABLE_BROADCASTS } from '../actions/broadcast'; // Default state for this reducer const defaultState = { @@ -9,7 +9,7 @@ const defaultState = { slippiConnectionStatus: ConnectionStatus.DISCONNECTED, isBroadcasting: false, isConnecting: false, - channels: [], + broadcasts: [], }; export default function broadcastReducer(state = defaultState, action) { @@ -22,8 +22,8 @@ export default function broadcastReducer(state = defaultState, action) { return setDolphinStatus(state, action); case SET_SLIPPI_STATUS: return setSlippiStatus(state, action); - case UPDATE_BROADCAST_CHANNELS: - return updateBroadcastChannels(state, action); + case UPDATE_VIEWABLE_BROADCASTS: + return updateViewableBroadcasts(state, action); default: return state; } @@ -60,10 +60,10 @@ function updateBroadcastStatus(oldState, state) { return newState; } -function updateBroadcastChannels(state, action) { - const { channels } = action; +function updateViewableBroadcasts(state, action) { + const { broadcasts } = action; return { ...state, - channels: channels, + broadcasts: broadcasts, }; } \ No newline at end of file diff --git a/package.json b/package.json index b5b6957db..47048426d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "slippi-desktop-app", "productName": "Slippi Desktop App", - "version": "1.5.1", + "version": "1.5.2-dev.4", "description": "Slippi Desktop App for browsing and playing replays.", "scripts": { "build": "concurrently \"yarn build-main\" \"yarn build-renderer\"", @@ -298,4 +298,4 @@ "pre-commit": "yarn lint --quiet" } } -} +} \ No newline at end of file From 7eeb527f0a07432df146cc35e150b4e84ff239d3 Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Fri, 16 Oct 2020 13:14:46 -0700 Subject: [PATCH 46/87] pass api version to service --- app/domain/BroadcastManager.js | 1 + app/domain/SpectateManager.js | 1 + 2 files changed, 2 insertions(+) diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index b8ea21b10..5157efc86 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -62,6 +62,7 @@ export class BroadcastManager { const headers = { password: password, + "api-version": 1, }; const user = firebase.auth().currentUser; if (user) { diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index 9900cbb76..113a0ad54 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -137,6 +137,7 @@ export class SpectateManager { const headers = { password: password, + "api-version": 1, }; const user = firebase.auth().currentUser; if (user) { From e410ff394d27d6fcc3b4401835b7b64e5809ba3a Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Tue, 20 Oct 2020 12:52:53 -0700 Subject: [PATCH 47/87] send end_game message on dolphin disconnect --- app/components/Broadcast.js | 5 +++-- app/domain/BroadcastManager.js | 11 +++++++++-- app/domain/SpectateManager.js | 32 ++++++++++++++++++++++---------- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 824b3f25e..996bb4d19 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -96,10 +96,11 @@ export default class Broadcast extends Component { renderBroadcasts() { const broadcasts = _.get(this.props.broadcast, 'broadcasts') || []; const broadcastEntries = _.map(broadcasts, broadcast => { - const name = _.get(broadcast, ['broadcaster', 'name']); + const name = _.get(broadcast, 'name'); + const broadcasterName = _.get(broadcast, ['broadcaster', 'name']); return ( -
{name} ({broadcast.id})
+
[{broadcasterName}] {name} ({broadcast.id})
+
); } From 616d8cfca89a59210a103b7c2df290af89d9dbad Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Tue, 20 Oct 2020 23:28:33 -0700 Subject: [PATCH 54/87] fix another getStageName call breaking stuff --- app/components/stats/GameProfile.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/components/stats/GameProfile.js b/app/components/stats/GameProfile.js index 2bd86500d..b6d164061 100644 --- a/app/components/stats/GameProfile.js +++ b/app/components/stats/GameProfile.js @@ -1,4 +1,5 @@ import React, { Component } from 'react'; +import log from 'electron-log'; import classNames from 'classnames'; import _ from 'lodash'; import PropTypes from 'prop-types'; @@ -228,7 +229,12 @@ export default class GameProfile extends Component { renderGameDetails() { const gameSettings = _.get(this.props.store, ['game', 'settings']) || {}; - const stageName = _.isNil(gameSettings.stageId) ? "Unknown" : stageUtils.getStageName(gameSettings.stageId); + let stageName = "Unknown"; + try { + stageName = stageUtils.getStageName(gameSettings.stageId); + } catch(err) { + log.error(err); + } const duration = _.get(this.props.store, ['game', 'stats', 'lastFrame']) || 0; From 52394a6143a1ed1b6598270ba647b5c3cdee3ccc Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 21 Oct 2020 18:22:25 -0700 Subject: [PATCH 55/87] Fix GameProfile loading due to unfiltering Originally the unfilter code only looked at the full list of files. Now we store the filtered list and full list and reference them based on filterReplays --- app/actions/fileLoader.js | 90 ++++++++++++++++++++++++------------ app/components/FileLoader.js | 37 ++++----------- app/reducers/fileLoader.js | 14 +++++- 3 files changed, 83 insertions(+), 58 deletions(-) diff --git a/app/actions/fileLoader.js b/app/actions/fileLoader.js index eff487512..f3ad91338 100644 --- a/app/actions/fileLoader.js +++ b/app/actions/fileLoader.js @@ -2,8 +2,8 @@ import _ from 'lodash'; import fs from 'fs'; import path from 'path'; import SlippiGame from '@slippi/slippi-js'; -import * as timeUtils from '../utils/time'; import { shell } from 'electron'; +import * as timeUtils from '../utils/time'; import { displayError } from './error'; import { gameProfileLoad } from './game'; @@ -16,6 +16,10 @@ export const LOAD_FILES_IN_FOLDER = 'LOAD_FILES_IN_FOLDER'; export const SET_STATS_GAME_PAGE = 'SET_STATS_GAME_PAGE'; export const STORE_SCROLL_POSITION = 'STORE_SCROLL_POSITION'; export const STORE_FILE_LOAD_STATE = 'STORE_FILE_LOAD_STATE'; +export const SET_FILTER_REPLAYS = 'SET_FILTER_REPLAYS'; + +const MIN_GAME_LENGTH_SECONDS = 30; +const MIN_GAME_LENGTH_FRAMES = MIN_GAME_LENGTH_SECONDS * 60; export function loadRootFolder() { return async (dispatch, getState) => { @@ -77,14 +81,17 @@ export function loadRootFolder() { await wait(10); // eslint-disable-line const filesAndFolders = await loadFilesInFolder(rootFolderPath); - const processedFiles = processFiles(filesAndFolders[0]); + const [unfilteredFiles, allFiles] = processFiles(filesAndFolders[0]); dispatch({ type: LOAD_FILES_IN_FOLDER, payload: { - files: processedFiles, + files: unfilteredFiles, + allFiles: allFiles, folders: filesAndFolders[1], - numFilteredFiles: filesAndFolders[0].length - processedFiles.length, + numErroredFiles: filesAndFolders[0].length - allFiles.length, + numDurationFilteredFiles: allFiles.length - unfilteredFiles.length, + numFilteredFiles: filesAndFolders[0].length - unfilteredFiles.length, }, }); }; @@ -104,14 +111,17 @@ export function changeFolderSelection(folder) { const currentPath = getState().fileLoader.selectedFolderFullPath; const filesAndFolders = await loadFilesInFolder(currentPath); - const processedFiles = processFiles(filesAndFolders[0]); + const [unfilteredFiles, allFiles] = processFiles(filesAndFolders[0]); dispatch({ type: LOAD_FILES_IN_FOLDER, payload: { - files: processedFiles, + files: unfilteredFiles, + allFiles: allFiles, folders: filesAndFolders[1], - numFilteredFiles: filesAndFolders[0].length - processedFiles.length, + numErroredFiles: filesAndFolders[0].length - allFiles.length, + numDurationFilteredFiles: allFiles.length - unfilteredFiles.length, + numFilteredFiles: filesAndFolders[0].length - unfilteredFiles.length, }, }); }; @@ -175,7 +185,8 @@ export function queueFiles(files) { export function setStatsGamePage(index) { return (dispatch, getState) => { - const files = getState().fileLoader.files; + const state = getState().fileLoader; + const files = (state.filterReplays ? state.files : state.allFiles) || []; let statsGameIndex = index; if (statsGameIndex >= files.length) { statsGameIndex = 0; @@ -194,22 +205,31 @@ export function setStatsGamePage(index) { } export function deleteSelections(selections) { - return (dispatch, getState) => { - const tempStore = getState().fileLoader.fileLoadState; - const filesToRender = tempStore.filesToRender; - for(const i of selections){ - shell.moveItemToTrash(i.fullPath); - filesToRender.splice(filesToRender.indexOf(i),1); - } - tempStore.filesToRender = filesToRender; - tempStore.filesOffset = filesToRender.length; - dispatch({ - type: STORE_FILE_LOAD_STATE, - payload: { - fileLoadState: tempStore, - }, - }); - }; + return (dispatch, getState) => { + const tempStore = getState().fileLoader.fileLoadState; + const filesToRender = tempStore.filesToRender; + _.each(selections, (selection, i) => { + shell.moveItemToTrash(selection.fullPath); + filesToRender.splice(i, 1); + }); + tempStore.filesToRender = filesToRender; + tempStore.filesOffset = filesToRender.length; + dispatch({ + type: STORE_FILE_LOAD_STATE, + payload: { + fileLoadState: tempStore, + }, + }); + }; +} + +export function setFilterReplays(val) { + return { + type: SET_FILTER_REPLAYS, + payload: { + filterReplays: val, + }, + } } async function loadFilesInFolder(folderPath) { @@ -294,9 +314,9 @@ async function wait(ms) { } function processFiles(files) { - let resultFiles = files; + let goodFiles = files; - resultFiles = resultFiles.filter(file => { + goodFiles = goodFiles.filter(file => { if (file.hasError) { // This will occur if an error was encountered while parsing return false; @@ -312,12 +332,24 @@ function processFiles(files) { return true; }); - resultFiles = _.orderBy( - resultFiles, + let filteredFiles = goodFiles.filter(file => { + const metadata = file.game.getMetadata() || {}; + const totalFrames = metadata.lastFrame || MIN_GAME_LENGTH_FRAMES + 1; + return totalFrames > MIN_GAME_LENGTH_FRAMES; + }) + + goodFiles = _.orderBy( + goodFiles, + ['startTime', 'fileName'], + ['desc', 'desc'] + ); + + filteredFiles = _.orderBy( + filteredFiles, ['startTime', 'fileName'], ['desc', 'desc'] ); // Filter out files that were shorter than 30 seconds - return resultFiles; + return [filteredFiles, goodFiles]; } diff --git a/app/components/FileLoader.js b/app/components/FileLoader.js index fda74d65a..a0ee63086 100644 --- a/app/components/FileLoader.js +++ b/app/components/FileLoader.js @@ -22,7 +22,6 @@ import Scroller from './common/Scroller'; const GAME_BATCH_SIZE = 50; const MIN_GAME_LENGTH_SECONDS = 30; -const MIN_GAME_LENGTH_FRAMES = MIN_GAME_LENGTH_SECONDS * 60; export default class FileLoader extends Component { static propTypes = { @@ -34,7 +33,8 @@ export default class FileLoader extends Component { storeScrollPosition: PropTypes.func.isRequired, storeFileLoadState: PropTypes.func.isRequired, setStatsGamePage: PropTypes.func.isRequired, - deleteSelections: PropTypes.func.isRequired, + deleteSelections: PropTypes.func.isRequired, + setFilterReplays: PropTypes.func.isRequired, // error actions dismissError: PropTypes.func.isRequired, @@ -49,9 +49,8 @@ export default class FileLoader extends Component { constructor(props) { super(props); + this.props.setFilterReplays(true); this.state = { - // Filter the replays by default. Gets reset when the component is unmounted - filterReplays: true, selections: [], }; } @@ -192,34 +191,16 @@ export default class FileLoader extends Component { ); } - /** - * Returns all the files which have not been filtered by game duration - */ - unfilteredFiles() { - const store = this.props.store || {}; - const allFiles = store.files || []; - return allFiles.filter((f) => { - if (this.state.filterReplays) { - // Files which have no metadata will be shown - return f.lastFrame === null || f.lastFrame >= MIN_GAME_LENGTH_FRAMES; - } - return true; - }); - } - renderFilteredFilesNotif() { const store = this.props.store || {}; if (store.isLoading) { return null; } - const allFiles = store.files || []; // These are the number of files that were initially removed probably because they're corrupted - const errorFileCount = _.get(this.props.store, 'numFilteredFiles'); - - const files = this.unfilteredFiles(); - const durationFilterCount = allFiles.length - files.length; - const totalFilteredCount = durationFilterCount + errorFileCount; + const errorFileCount = _.get(store, 'numErroredFiles'); + const durationFilterCount = _.get(store, 'numDurationFilteredFiles'); + const totalFilteredCount = _.get(store, 'numFilteredFiles'); if (totalFilteredCount === 0) { return null; } @@ -235,7 +216,7 @@ export default class FileLoader extends Component { contentText = `${errorFileCount} corrupt files detected.`; } } - const showHideButton = durationFilterCount > 0 && this.state.filterReplays; + const showHideButton = durationFilterCount > 0 && store.filterReplays; const onShowAnywayClick = () => { // Clear the currently loaded files @@ -244,8 +225,8 @@ export default class FileLoader extends Component { filesOffset: 0, }); // Clear the selection and disable replay filter + this.props.setFilterReplays(false); this.setState({ - filterReplays: false, selections: [], }); } @@ -339,7 +320,7 @@ export default class FileLoader extends Component { renderFileSelection() { const store = this.props.store || {}; - const allFiles = this.unfilteredFiles(); + const allFiles = (store.filterReplays ? store.files : store.allFiles) || []; const filesToRender = _.get(store, ['fileLoadState', 'filesToRender']) || []; const filesOffset = _.get(store, ['fileLoadState', 'filesOffset']) || 0; diff --git a/app/reducers/fileLoader.js b/app/reducers/fileLoader.js index 6d05f1c6e..049d73587 100644 --- a/app/reducers/fileLoader.js +++ b/app/reducers/fileLoader.js @@ -1,5 +1,5 @@ import { - LOAD_ROOT_FOLDER, CHANGE_FOLDER_SELECTION, LOAD_FILES_IN_FOLDER, STORE_SCROLL_POSITION, SET_STATS_GAME_PAGE, STORE_FILE_LOAD_STATE, + LOAD_ROOT_FOLDER, CHANGE_FOLDER_SELECTION, LOAD_FILES_IN_FOLDER, STORE_SCROLL_POSITION, SET_STATS_GAME_PAGE, STORE_FILE_LOAD_STATE, SET_FILTER_REPLAYS, } from '../actions/fileLoader'; import DolphinManager from '../domain/DolphinManager'; @@ -38,6 +38,8 @@ export default function fileLoader(state = defaultState, action) { return storeFileLoadState(state, action); case SET_STATS_GAME_PAGE: return setStatsGamePage(state, action); + case SET_FILTER_REPLAYS: + return setFilterReplays(state, action); default: return state; } @@ -113,7 +115,10 @@ function loadFilesInFolder(state, action) { ...state, isLoading: false, files: action.payload.files, + allFiles: action.payload.allFiles, folders: folders, + numErroredFiles: action.payload.numErroredFiles, + numDurationFilteredFiles: action.payload.numDurationFilteredFiles, numFilteredFiles: action.payload.numFilteredFiles, fileLoadState: {}, }; @@ -139,3 +144,10 @@ function setStatsGamePage(state, action) { statsGameIndex: action.payload.statsGameIndex, }; } + +function setFilterReplays(state, action) { + return { + ...state, + filterReplays: action.payload.filterReplays, + } +} From 23f386cf02870c5cb07757c4ec2d3cbe123a112c Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 21 Oct 2020 18:58:21 -0700 Subject: [PATCH 56/87] export MIN_GAME_LENGTH_SECONDS --- app/actions/fileLoader.js | 2 +- app/components/FileLoader.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/actions/fileLoader.js b/app/actions/fileLoader.js index f3ad91338..4b2f4d9cf 100644 --- a/app/actions/fileLoader.js +++ b/app/actions/fileLoader.js @@ -18,7 +18,7 @@ export const STORE_SCROLL_POSITION = 'STORE_SCROLL_POSITION'; export const STORE_FILE_LOAD_STATE = 'STORE_FILE_LOAD_STATE'; export const SET_FILTER_REPLAYS = 'SET_FILTER_REPLAYS'; -const MIN_GAME_LENGTH_SECONDS = 30; +export const MIN_GAME_LENGTH_SECONDS = 30; const MIN_GAME_LENGTH_FRAMES = MIN_GAME_LENGTH_SECONDS * 60; export function loadRootFolder() { diff --git a/app/components/FileLoader.js b/app/components/FileLoader.js index a0ee63086..703697df5 100644 --- a/app/components/FileLoader.js +++ b/app/components/FileLoader.js @@ -19,9 +19,9 @@ import PageHeader from './common/PageHeader'; import FolderBrowser from './common/FolderBrowser'; import PageWrapper from './PageWrapper'; import Scroller from './common/Scroller'; +import { MIN_GAME_LENGTH_SECONDS } from '../actions/fileLoader'; const GAME_BATCH_SIZE = 50; -const MIN_GAME_LENGTH_SECONDS = 30; export default class FileLoader extends Component { static propTypes = { From ef55fd993e40d7623007dbdc66b68c7ac7e1c7e6 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 21 Oct 2020 19:11:06 -0700 Subject: [PATCH 57/87] remove entries from filesToRender properly --- app/actions/fileLoader.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/actions/fileLoader.js b/app/actions/fileLoader.js index 4b2f4d9cf..7ea3ca6fc 100644 --- a/app/actions/fileLoader.js +++ b/app/actions/fileLoader.js @@ -207,10 +207,9 @@ export function setStatsGamePage(index) { export function deleteSelections(selections) { return (dispatch, getState) => { const tempStore = getState().fileLoader.fileLoadState; - const filesToRender = tempStore.filesToRender; - _.each(selections, (selection, i) => { + const filesToRender = _.without(tempStore.filesToRender, ...selections); + _.each(selections, (selection) => { shell.moveItemToTrash(selection.fullPath); - filesToRender.splice(i, 1); }); tempStore.filesToRender = filesToRender; tempStore.filesOffset = filesToRender.length; From c1c3358983e7c676ddced327920a64d91c2d73ff Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Tue, 3 Nov 2020 10:22:10 -0800 Subject: [PATCH 58/87] fix deleting files --- app/actions/fileLoader.js | 11 ++++++++--- app/reducers/fileLoader.js | 13 ++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/actions/fileLoader.js b/app/actions/fileLoader.js index 7ea3ca6fc..b91361b26 100644 --- a/app/actions/fileLoader.js +++ b/app/actions/fileLoader.js @@ -17,6 +17,7 @@ export const SET_STATS_GAME_PAGE = 'SET_STATS_GAME_PAGE'; export const STORE_SCROLL_POSITION = 'STORE_SCROLL_POSITION'; export const STORE_FILE_LOAD_STATE = 'STORE_FILE_LOAD_STATE'; export const SET_FILTER_REPLAYS = 'SET_FILTER_REPLAYS'; +export const DELETE_FILE = 'DELETE_FILE'; export const MIN_GAME_LENGTH_SECONDS = 30; const MIN_GAME_LENGTH_FRAMES = MIN_GAME_LENGTH_SECONDS * 60; @@ -206,17 +207,21 @@ export function setStatsGamePage(index) { export function deleteSelections(selections) { return (dispatch, getState) => { - const tempStore = getState().fileLoader.fileLoadState; - const filesToRender = _.without(tempStore.filesToRender, ...selections); + const tempStore = getState().fileLoader; + const filesToRender = _.without(tempStore.fileLoadState.filesToRender, ...selections); + const files = _.without(tempStore.files, ...selections); + const allFiles = _.without(tempStore.allFiles, ...selections); _.each(selections, (selection) => { shell.moveItemToTrash(selection.fullPath); }); tempStore.filesToRender = filesToRender; tempStore.filesOffset = filesToRender.length; dispatch({ - type: STORE_FILE_LOAD_STATE, + type: DELETE_FILE, payload: { fileLoadState: tempStore, + files: files, + allFiles: allFiles, }, }); }; diff --git a/app/reducers/fileLoader.js b/app/reducers/fileLoader.js index 049d73587..4386d5e33 100644 --- a/app/reducers/fileLoader.js +++ b/app/reducers/fileLoader.js @@ -1,5 +1,5 @@ import { - LOAD_ROOT_FOLDER, CHANGE_FOLDER_SELECTION, LOAD_FILES_IN_FOLDER, STORE_SCROLL_POSITION, SET_STATS_GAME_PAGE, STORE_FILE_LOAD_STATE, SET_FILTER_REPLAYS, + LOAD_ROOT_FOLDER, CHANGE_FOLDER_SELECTION, LOAD_FILES_IN_FOLDER, STORE_SCROLL_POSITION, SET_STATS_GAME_PAGE, STORE_FILE_LOAD_STATE, SET_FILTER_REPLAYS, DELETE_FILE, } from '../actions/fileLoader'; import DolphinManager from '../domain/DolphinManager'; @@ -40,6 +40,8 @@ export default function fileLoader(state = defaultState, action) { return setStatsGamePage(state, action); case SET_FILTER_REPLAYS: return setFilterReplays(state, action); + case DELETE_FILE: + return deleteFile(state, action); default: return state; } @@ -151,3 +153,12 @@ function setFilterReplays(state, action) { filterReplays: action.payload.filterReplays, } } + +function deleteFile(state, action) { + return { + ...state, + allFiles: action.payload.allFiles, + files: action.payload.files, + fileLoadState: action.payload.fileLoadState, + } +} From d99cb5c377f4b4bd7f4edb955a5e1fa05189f08d Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Tue, 3 Nov 2020 10:32:40 -0800 Subject: [PATCH 59/87] pick the correct file when loading the GameProfile --- app/containers/GameProfilePage.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/containers/GameProfilePage.js b/app/containers/GameProfilePage.js index 228c78595..50b67aefc 100644 --- a/app/containers/GameProfilePage.js +++ b/app/containers/GameProfilePage.js @@ -7,7 +7,8 @@ import { dismissError } from "../actions/error"; function mapStateToProps(state) { const index = state.fileLoader.statsGameIndex; - const file = state.fileLoader.files[index] || null; + const files = state.fileLoader.filterReplays ? state.fileLoader.files : state.fileLoader.allFiles; + const file = files[index] || null; return { store: state.game, statsGameIndex: index, From 8e9748268b91da784cf874677f7360ec7e76e37b Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Tue, 3 Nov 2020 10:39:36 -0800 Subject: [PATCH 60/87] don't update filterReplays on POP --- app/components/FileLoader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/FileLoader.js b/app/components/FileLoader.js index 703697df5..f85388759 100644 --- a/app/components/FileLoader.js +++ b/app/components/FileLoader.js @@ -49,7 +49,6 @@ export default class FileLoader extends Component { constructor(props) { super(props); - this.props.setFilterReplays(true); this.state = { selections: [], }; @@ -60,6 +59,7 @@ export default class FileLoader extends Component { // The action when returning from the stats page is "POP". The action when coming from the // main menu is "PUSH". When coming from the main menu, we want to reload the files such that // any new files show up correctly + this.props.setFilterReplays(true); this.props.loadRootFolder(); // Arriving at the file browser from the top level menu should reset the scroll position because From 5bf70e7417c432abc92390c06385534bd98edb52 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Mon, 17 Aug 2020 18:58:09 -0700 Subject: [PATCH 61/87] update electron builder --- package.json | 2 +- yarn.lock | 1038 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 690 insertions(+), 350 deletions(-) diff --git a/package.json b/package.json index 9b41a1310..5c7676256 100644 --- a/package.json +++ b/package.json @@ -203,7 +203,7 @@ "detect-port": "^1.3.0", "dotenv-webpack": "^2.0.0", "electron": "^4.1.4", - "electron-builder": "^20.34.0", + "electron-builder": "^22.8.0", "electron-devtools-installer": "^2.2.4", "enzyme": "^3.7.0", "enzyme-adapter-react-16": "^1.7.0", diff --git a/yarn.lock b/yarn.lock index 4abd63c0b..d9f41ec05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"7zip-bin@~4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-4.1.0.tgz#33eff662a5c39c0c2061170cc003c5120743fff0" - integrity sha512-AsnBZN3a8/JcNt+KPkGGODaA4c7l3W5+WpeKgGSbstSLxqWtTXqd1ieJGBQ8IFCtRg8DmmKUcSkIkUc0A4p3YA== +"7zip-bin@~5.0.3": + version "5.0.3" + resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.0.3.tgz#bc5b5532ecafd923a61f2fb097e3b108c0106a3f" + integrity sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA== "7zip@0.0.6": version "0.0.6" @@ -938,6 +938,14 @@ lodash "^4.17.10" to-fast-properties "^2.0.0" +"@develar/schema-utils@~2.6.5": + version "2.6.5" + resolved "https://registry.yarnpkg.com/@develar/schema-utils/-/schema-utils-2.6.5.tgz#3ece22c5838402419a6e0425f85742b961d9b6c6" + integrity sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig== + dependencies: + ajv "^6.12.0" + ajv-keywords "^3.4.1" + "@firebase/analytics-types@0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.4.0.tgz#d6716f9fa36a6e340bc0ecfe68af325aa6f60508" @@ -1339,6 +1347,11 @@ resolved "https://registry.yarnpkg.com/@shelacek/ubjson/-/ubjson-1.0.1.tgz#009d39ea22fa80e036f97e936650951a8225fafe" integrity sha512-0vlllP3M7fUElSd4239wmnv6SqDeymJgjRkb/iusOyDN4I0xjc8hrX4Zk/KYoAesgSdsnnSwhOU7g+IewmdaAw== +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + "@sinonjs/commons@^1.0.2", "@sinonjs/commons@^1.2.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.3.0.tgz#50a2754016b6f30a994ceda6d9a0a8c36adda849" @@ -1375,6 +1388,13 @@ reconnect-core "^1.3.0" semver "^7.3.2" +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + "@types/caseless@*": version "0.12.1" resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.1.tgz#9794c69c8385d0192acc471a540d1f8e0d16218a" @@ -1385,6 +1405,11 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/debug@^4.1.5": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" + integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== + "@types/duplexify@^3.5.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@types/duplexify/-/duplexify-3.6.0.tgz#dfc82b64bd3a2168f5bd26444af165bf0237dcd8" @@ -1404,6 +1429,13 @@ dependencies: "@types/node" "*" +"@types/fs-extra@^9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.1.tgz#91c8fc4c51f6d5dbe44c2ca9ab09310bd00c7918" + integrity sha512-B42Sxuaz09MhC3DDeW5kubRcQ5by4iuVQ0cRRWM2lggLzAa/KVom0Aft/208NgMvNQQZ86s5rVcqDdn/SH0/mg== + dependencies: + "@types/node" "*" + "@types/lodash@^4.14.72": version "4.14.119" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.119.tgz#be847e5f4bc3e35e46d041c394ead8b603ad8b39" @@ -1454,6 +1486,18 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.5.tgz#9da44ed75571999b65c37b60c9b2b88db54c585d" integrity sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg== +"@types/yargs-parser@*": + version "15.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" + integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== + +"@types/yargs@^15.0.5": + version "15.0.5" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.5.tgz#947e9a6561483bdee9adffc983e91a6902af8b79" + integrity sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w== + dependencies: + "@types/yargs-parser" "*" + "@webassemblyjs/ast@1.7.11": version "1.7.11" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.11.tgz#b988582cafbb2b095e8b556526f30c90d057cace" @@ -1703,11 +1747,16 @@ ajv-errors@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== -ajv-keywords@^3.1.0, ajv-keywords@^3.2.0: +ajv-keywords@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= +ajv-keywords@^3.4.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + ajv@^6.1.0, ajv@^6.5.3, ajv@^6.5.5, ajv@^6.6.1: version "6.6.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d" @@ -1718,6 +1767,16 @@ ajv@^6.1.0, ajv@^6.5.3, ajv@^6.5.5, ajv@^6.6.1: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.12.0: + version "6.12.4" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" + integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + alphanum-sort@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" @@ -1728,12 +1787,12 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= -ansi-align@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" - integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38= +ansi-align@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" + integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== dependencies: - string-width "^2.0.0" + string-width "^3.0.0" ansi-colors@^1.0.1: version "1.1.0" @@ -1798,6 +1857,11 @@ ansi-regex@^4.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w== +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + ansi-regex@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" @@ -1815,7 +1879,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== @@ -1836,40 +1900,38 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -app-builder-bin@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-2.6.1.tgz#aa97f82d341dfa6f1269d78955482d619cc613ed" - integrity sha512-W0l85O+s6lOaziWqAhszPfwiG0s15FvMBP9j9i/bknsMccUkwN60u4Cy7yYtf6akCUDuJenLqpTX4/xvkq1egw== +app-builder-bin@3.5.9: + version "3.5.9" + resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.9.tgz#a3ac0c25286bac68357321cb2eaf7128b0bc0a4f" + integrity sha512-NSjtqZ3x2kYiDp3Qezsgukx/AUzKPr3Xgf9by4cYt05ILWGAptepeeu0Uv+7MO+41o6ujhLixTou8979JGg2Kg== -app-builder-lib@20.38.4, app-builder-lib@~20.38.3: - version "20.38.4" - resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-20.38.4.tgz#71a515d01f4f2bd48a67495804f659a46c35303c" - integrity sha512-JbuAJQBndcCW6BJVIb2tPjM5wiuIjz2LUlbyVxNIawM2wFKUBV9kr0N3RNBJFxcrCEuA9oprMUCoymJdrMUVfA== +app-builder-lib@22.8.0: + version "22.8.0" + resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-22.8.0.tgz#342a8976f50ae35cfd07412dbfd4f6c895b32eac" + integrity sha512-RGaIRjCUrqkmh6QOGsyekQPEOaVynHfmeh8JZuyUymFYUOFdzBbPamkA2nhBVBTkkgfjRHsxK7LhedFKPzvWEQ== dependencies: - "7zip-bin" "~4.1.0" - app-builder-bin "2.6.1" + "7zip-bin" "~5.0.3" + "@develar/schema-utils" "~2.6.5" async-exit-hook "^2.0.1" - bluebird-lst "^1.0.6" - builder-util "9.6.1" - builder-util-runtime "8.1.0" + bluebird-lst "^1.0.9" + builder-util "22.8.0" + builder-util-runtime "8.7.2" chromium-pickle-js "^0.2.0" - debug "^4.1.0" - ejs "^2.6.1" - electron-osx-sign "0.4.11" - electron-publish "20.38.3" - fs-extra-p "^7.0.0" - hosted-git-info "^2.7.1" + debug "^4.1.1" + ejs "^3.1.3" + electron-publish "22.8.0" + fs-extra "^9.0.1" + hosted-git-info "^3.0.5" is-ci "^2.0.0" - isbinaryfile "^3.0.3" - js-yaml "^3.12.0" - lazy-val "^1.0.3" + isbinaryfile "^4.0.6" + js-yaml "^3.14.0" + lazy-val "^1.0.4" minimatch "^3.0.4" - normalize-package-data "^2.4.0" - plist "^3.0.1" - read-config-file "3.2.0" - sanitize-filename "^1.6.1" - semver "^5.6.0" - temp-file "^3.3.2" + normalize-package-data "^2.5.0" + read-config-file "6.0.0" + sanitize-filename "^1.6.3" + semver "^7.3.2" + temp-file "^3.3.7" append-transform@^0.4.0: version "0.4.0" @@ -2136,6 +2198,11 @@ async@0.2.6: resolved "https://registry.yarnpkg.com/async/-/async-0.2.6.tgz#ad3f373d9249ae324881565582bc90e152abbd68" integrity sha1-rT83PZJJrjJIgVZVgryQ4VKrvWg= +async@0.9.x: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= + async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -2160,6 +2227,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -2977,7 +3049,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base64-js@^1.0.2, base64-js@^1.1.2, base64-js@^1.2.3, base64-js@^1.3.0: +base64-js@^1.0.2, base64-js@^1.1.2, base64-js@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== @@ -3064,12 +3136,19 @@ bluebird-lst@^1.0.6: dependencies: bluebird "^3.5.2" -bluebird@^3.4.6: +bluebird-lst@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/bluebird-lst/-/bluebird-lst-1.0.9.tgz#a64a0e4365658b9ab5fe875eb9dfb694189bb41c" + integrity sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw== + dependencies: + bluebird "^3.5.5" + +bluebird@^3.4.6, bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.5.2, bluebird@^3.5.3: +bluebird@^3.5.1, bluebird@^3.5.2, bluebird@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== @@ -3117,18 +3196,19 @@ bowser@1.6.0: resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.6.0.tgz#37fc387b616cb6aef370dab4d6bd402b74c5c54d" integrity sha1-N/w4e2Fstq7zcNq01r1AK3TFxU0= -boxen@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" - integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== +boxen@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" + integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== dependencies: - ansi-align "^2.0.0" - camelcase "^4.0.0" - chalk "^2.0.1" - cli-boxes "^1.0.0" - string-width "^2.0.0" - term-size "^1.2.0" - widest-line "^2.0.0" + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^3.0.0" + cli-boxes "^2.2.0" + string-width "^4.1.0" + term-size "^2.1.0" + type-fest "^0.8.1" + widest-line "^3.1.0" brace-expansion@^1.1.7: version "1.1.11" @@ -3337,7 +3417,15 @@ bufferutil@^4.0.1: dependencies: node-gyp-build "~3.7.0" -builder-util-runtime@8.1.0, builder-util-runtime@^8.1.0, builder-util-runtime@~8.1.0: +builder-util-runtime@8.7.2: + version "8.7.2" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.7.2.tgz#d93afc71428a12789b437e13850e1fa7da956d72" + integrity sha512-xBqv+8bg6cfnzAQK1k3OGpfaHg+QkPgIgpEkXNhouZ0WiUkyZCftuRc2LYzQrLucFywpa14Xbc6+hTbpq83yRA== + dependencies: + debug "^4.1.1" + sax "^1.2.4" + +builder-util-runtime@~8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.1.0.tgz#dd7fca995d48ceee7580b4851ca057566c94601e" integrity sha512-s1mlJ28mv+56Iebh6c9aXjVe11O3Z0cDTwAGeB0PCcUzHA37fDxGgS8ZGoYNMZP+rBHj21d/od1wuYofTVLaQg== @@ -3347,23 +3435,25 @@ builder-util-runtime@8.1.0, builder-util-runtime@^8.1.0, builder-util-runtime@~8 fs-extra-p "^7.0.0" sax "^1.2.4" -builder-util@9.6.1, builder-util@~9.6.0: - version "9.6.1" - resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-9.6.1.tgz#4625620b1535fe40dcacb178d24fe56d0d7c8957" - integrity sha512-8MljKTjeV+A+LLVexuWEV3EpWbiUcsHHrB4Bg2qNo/3dC+vTo6g/27+W3Ij7Ij1UTobSkNBstFieWijXJCco9A== - dependencies: - "7zip-bin" "~4.1.0" - app-builder-bin "2.6.1" - bluebird-lst "^1.0.6" - builder-util-runtime "^8.1.0" - chalk "^2.4.1" - debug "^4.1.0" - fs-extra-p "^7.0.0" +builder-util@22.8.0: + version "22.8.0" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-22.8.0.tgz#01684085d1f2370b1bd182f69cbd007426f63f64" + integrity sha512-H80P1JzVy3TGpi63x81epQDK24XalL034+jAZlrPb5IhLtYmnNNdxCCAVJvg3VjSISd73Y71O+uhqCxWpqbPHw== + dependencies: + "7zip-bin" "~5.0.3" + "@types/debug" "^4.1.5" + "@types/fs-extra" "^9.0.1" + app-builder-bin "3.5.9" + bluebird-lst "^1.0.9" + builder-util-runtime "8.7.2" + chalk "^4.1.0" + debug "^4.1.1" + fs-extra "^9.0.1" is-ci "^2.0.0" - js-yaml "^3.12.0" - source-map-support "^0.5.9" - stat-mode "^0.2.2" - temp-file "^3.3.2" + js-yaml "^3.14.0" + source-map-support "^0.5.19" + stat-mode "^1.0.0" + temp-file "^3.3.7" builtin-modules@^1.0.0: version "1.1.1" @@ -3415,6 +3505,19 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -3490,7 +3593,7 @@ camelcase@^3.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= -camelcase@^4.0.0, camelcase@^4.1.0: +camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= @@ -3500,6 +3603,11 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + caniuse-api@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" @@ -3527,11 +3635,6 @@ capture-exit@^1.2.0: dependencies: rsvp "^3.3.3" -capture-stack-trace@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" - integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw== - caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -3574,6 +3677,22 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.0, chalk@^2.4.1, chalk@^2.4 escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + character-entities-html4@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.2.tgz#c44fdde3ce66b52e8d321d6c1bf46101f0150610" @@ -3722,10 +3841,10 @@ classnames@^2.2.6: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== -cli-boxes@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" - integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= +cli-boxes@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" + integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== cli-cursor@^2.1.0: version "2.1.0" @@ -3784,6 +3903,13 @@ clone-regexp@^1.0.0: is-regexp "^1.0.0" is-supported-regexp-flag "^1.0.0" +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + clone@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" @@ -3840,11 +3966,6 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-convert@~0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd" - integrity sha1-vbbGnOZg+t/+CwAHzER+G59ygr0= - color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" @@ -3913,11 +4034,6 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -compare-version@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/compare-version/-/compare-version-0.1.2.tgz#0162ec2d9351f5ddd59a9202cba935366a725080" - integrity sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA= - component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" @@ -4000,18 +4116,6 @@ concurrently@^4.1.0: tree-kill "^1.1.0" yargs "^12.0.1" -configstore@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" - integrity sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw== - dependencies: - dot-prop "^4.1.0" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - unique-string "^1.0.0" - write-file-atomic "^2.0.0" - xdg-basedir "^3.0.0" - configstore@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7" @@ -4024,6 +4128,18 @@ configstore@^4.0.0: write-file-atomic "^2.0.0" xdg-basedir "^3.0.0" +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + connect-history-api-fallback@^1.3.0: version "1.6.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" @@ -4161,13 +4277,6 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.0.0" -create-error-class@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" - integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y= - dependencies: - capture-stack-trace "^1.0.0" - create-hash@^1.1.0, create-hash@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" @@ -4267,6 +4376,11 @@ crypto-random-string@^1.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + css-color-names@0.0.4, css-color-names@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" @@ -4550,7 +4664,7 @@ debug@2.6.9, debug@^2.1.2, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6. dependencies: ms "2.0.0" -debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0: +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -4596,6 +4710,13 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + dedent@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.4.0.tgz#87defd040bd4c1595d963282ec57f3c2a8525642" @@ -4658,6 +4779,11 @@ default-require-extensions@^1.0.0: dependencies: strip-bom "^2.0.0" +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -4803,19 +4929,17 @@ discontinuous-range@1.0.0: resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo= -dmg-builder@6.5.3: - version "6.5.3" - resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-6.5.3.tgz#95afe3deab33fd874f68d299bc71b481e94f5312" - integrity sha512-ZNl4GFBg6rdFplnuoK56iftxh/qgM7rXJUxgl21eK4WsjxgQwtQ0REZo+pDSL4OzVeyOO8MMNWSNQcCsBLiDyA== +dmg-builder@22.8.0: + version "22.8.0" + resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-22.8.0.tgz#2b17127837ed444db3086317eda5cf8912f6e6a9" + integrity sha512-orePWjcrl97SYLA8F/6UUtbXJSoZCYu5KOP1lVqD4LOomr8bjGDyEVYZmZYcg5WqKmXucdmO6OpqgzH/aRMMuA== dependencies: - app-builder-lib "~20.38.3" - bluebird-lst "^1.0.6" - builder-util "~9.6.0" - fs-extra-p "^7.0.0" - iconv-lite "^0.4.24" - js-yaml "^3.12.0" - parse-color "^1.0.0" - sanitize-filename "^1.6.1" + app-builder-lib "22.8.0" + builder-util "22.8.0" + fs-extra "^9.0.1" + iconv-lite "^0.6.2" + js-yaml "^3.14.0" + sanitize-filename "^1.6.3" dns-equal@^1.0.0: version "1.0.0" @@ -4922,6 +5046,13 @@ dot-prop@^4.1.0, dot-prop@^4.1.1: dependencies: is-obj "^1.0.0" +dot-prop@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" + integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== + dependencies: + is-obj "^2.0.0" + dotenv-defaults@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/dotenv-defaults/-/dotenv-defaults-2.0.1.tgz#ea6f9632b3b5cc55e48b736760def5561f1cb7c0" @@ -4929,10 +5060,10 @@ dotenv-defaults@^2.0.0: dependencies: dotenv "^8.2.0" -dotenv-expand@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-4.2.0.tgz#def1f1ca5d6059d24a766e587942c21106ce1275" - integrity sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU= +dotenv-expand@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" + integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== dotenv-webpack@^2.0.0: version "2.0.0" @@ -4941,11 +5072,6 @@ dotenv-webpack@^2.0.0: dependencies: dotenv-defaults "^2.0.0" -dotenv@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" - integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== - dotenv@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" @@ -5011,29 +5137,37 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== +ejs@^3.1.3: + version "3.1.5" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.5.tgz#aed723844dc20acb4b170cd9ab1017e476a0d93b" + integrity sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w== + dependencies: + jake "^10.6.1" + ejs@~2.5.6: version "2.5.9" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.9.tgz#7ba254582a560d267437109a68354112475b0ce5" integrity sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ== -electron-builder@^20.34.0: - version "20.38.4" - resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.38.4.tgz#67727529ffb87e7fdd78b3a84ea0d6c22bf04ec2" - integrity sha512-WHOr3Rz2wktxV5TqmRL6woO9/wrIZeRfJPSEXOhgfgLskE5Sp2Aer0zAF7lHNqXuG6JhU+0I9IYFAxa73MTs9w== - dependencies: - app-builder-lib "20.38.4" - bluebird-lst "^1.0.6" - builder-util "9.6.1" - builder-util-runtime "8.1.0" - chalk "^2.4.1" - dmg-builder "6.5.3" - fs-extra-p "^7.0.0" +electron-builder@^22.8.0: + version "22.8.0" + resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.8.0.tgz#d2c9fc5438c834e41fd794a271fca200165a3bad" + integrity sha512-dUv4F3srJouqxhWivtKqSoQP4Df6vYgjooGdzms+iYMTFi9f0b4LlEbr7kgsPvte8zAglee7VOGOODkCRJDkUQ== + dependencies: + "@types/yargs" "^15.0.5" + app-builder-lib "22.8.0" + bluebird-lst "^1.0.9" + builder-util "22.8.0" + builder-util-runtime "8.7.2" + chalk "^4.1.0" + dmg-builder "22.8.0" + fs-extra "^9.0.1" is-ci "^2.0.0" - lazy-val "^1.0.3" - read-config-file "3.2.0" - sanitize-filename "^1.6.1" - update-notifier "^2.5.0" - yargs "^12.0.5" + lazy-val "^1.0.4" + read-config-file "6.0.0" + sanitize-filename "^1.6.3" + update-notifier "^4.1.0" + yargs "^15.3.1" electron-chromedriver@~3.0.0: version "3.0.0" @@ -5101,30 +5235,19 @@ electron-log@^2.2.17: resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-2.2.17.tgz#e71e2ebb949fc96ded7cdb99eeee7202e48981d2" integrity sha512-v+Af5W5z99ehhaLOfE9eTSXUwjzh2wFlQjz51dvkZ6ZIrET6OB/zAZPvsuwT6tm3t5x+M1r+Ed3U3xtPZYAyuQ== -electron-osx-sign@0.4.11: - version "0.4.11" - resolved "https://registry.yarnpkg.com/electron-osx-sign/-/electron-osx-sign-0.4.11.tgz#8377732fe7b207969f264b67582ee47029ce092f" - integrity sha512-VVd40nrnVqymvFrY9ZkOYgHJOvexHHYTR3di/SN+mjJ0OWhR1I8BRVj3U+Yamw6hnkZZNKZp52rqL5EFAAPFkQ== +electron-publish@22.8.0: + version "22.8.0" + resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.8.0.tgz#7f410fe043abc5d3d896c4ee9eea7a43ea352c7d" + integrity sha512-uM0Zdi9hUqqGOrPj478v7toTvV1Kgto1w11rIiI168batiXAJvNLD8VZRfehOrZT0ibUyZlw8FtxoGCrjyHUOw== dependencies: - bluebird "^3.5.0" - compare-version "^0.1.2" - debug "^2.6.8" - isbinaryfile "^3.0.2" - minimist "^1.2.0" - plist "^3.0.1" - -electron-publish@20.38.3: - version "20.38.3" - resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-20.38.3.tgz#7c162904f728ba2bbf2640bc3620b65ce1061ce3" - integrity sha512-Qomq253NT5DfjUZgFSx6p+gheU5YhM6zZ67fTtBZvwyk0v8HwxNXfa8fZT7h+1c3BwEmjusTbmjZRNW/XZBXFA== - dependencies: - bluebird-lst "^1.0.6" - builder-util "~9.6.0" - builder-util-runtime "^8.1.0" - chalk "^2.4.1" - fs-extra-p "^7.0.0" - lazy-val "^1.0.3" - mime "^2.4.0" + "@types/fs-extra" "^9.0.1" + bluebird-lst "^1.0.9" + builder-util "22.8.0" + builder-util-runtime "8.7.2" + chalk "^4.1.0" + fs-extra "^9.0.1" + lazy-val "^1.0.4" + mime "^2.4.6" electron-settings@^3.2.0: version "3.2.0" @@ -5199,6 +5322,11 @@ emoji-regex@^6.5.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.5.1.tgz#9baea929b155565c11ea41c6626eaa65cef992c2" integrity sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ== +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -5409,6 +5537,11 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.3: d "^1.0.1" ext "^1.1.2" +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" + integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -5984,6 +6117,11 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + fast-glob@^2.0.2: version "2.2.6" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.6.tgz#a5d5b697ec8deda468d85a74035290a025a95295" @@ -6095,6 +6233,13 @@ file-loader@^2.0.0: loader-utils "^1.0.2" schema-utils "^1.0.0" +filelist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.1.tgz#f10d1a3ae86c1694808e8f20906f43d4c9132dbb" + integrity sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ== + dependencies: + minimatch "^3.0.4" + filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -6366,6 +6511,16 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" + integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^1.0.0" + fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" @@ -6524,13 +6679,20 @@ get-stream@^3.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= -get-stream@^4.0.0: +get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== dependencies: pump "^3.0.0" +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -6594,12 +6756,12 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@~7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -global-dirs@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" - integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= +global-dirs@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201" + integrity sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A== dependencies: - ini "^1.3.4" + ini "^1.3.5" global-modules-path@^2.3.0: version "2.3.1" @@ -6746,22 +6908,22 @@ google-p12-pem@^3.0.0: dependencies: node-forge "^0.10.0" -got@^6.7.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" - integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA= +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== dependencies: - create-error-class "^3.0.0" + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-redirect "^1.0.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - lowercase-keys "^1.0.0" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - unzip-response "^2.0.1" - url-parse-lax "^1.0.0" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" graceful-fs@^4.1.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.15" @@ -6902,6 +7064,11 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" @@ -6943,6 +7110,11 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + has@^1.0.0, has@^1.0.1, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -7049,11 +7221,18 @@ hoopy@^0.1.2: resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== -hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: +hosted-git-info@^2.1.4: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== +hosted-git-info@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.5.tgz#bea87905ef7317442e8df3087faa3c842397df03" + integrity sha512-i4dpK6xj9BIpVOTboXIlKG9+8HMKggcrMX7WA24xZtKwX0TPelq/rbaS5rCKeNX8sJXZJGdSxpnEGtta+wismQ== + dependencies: + lru-cache "^6.0.0" + hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" @@ -7108,6 +7287,11 @@ htmlparser2@^3.9.1, htmlparser2@^3.9.2: inherits "^2.0.1" readable-stream "^3.0.6" +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" @@ -7733,18 +7917,18 @@ is-hexadecimal@^1.0.0: resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz#b6e710d7d07bb66b98cb8cece5c9b4921deeb835" integrity sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A== -is-installed-globally@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" - integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= +is-installed-globally@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" + integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== dependencies: - global-dirs "^0.1.0" - is-path-inside "^1.0.0" + global-dirs "^2.0.1" + is-path-inside "^3.0.1" -is-npm@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" - integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= +is-npm@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" + integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== is-number-object@^1.0.3: version "1.0.3" @@ -7775,6 +7959,11 @@ is-obj@^1.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + is-object@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" @@ -7799,6 +7988,11 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-path-inside@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" + integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== + is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -7826,11 +8020,6 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= -is-redirect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" - integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= - is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" @@ -7848,17 +8037,12 @@ is-resolvable@^1.0.0: resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== -is-retry-allowed@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" - integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= - is-stream-ended@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw== -is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= @@ -7927,6 +8111,11 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + is@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79" @@ -7942,12 +8131,10 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isbinaryfile@^3.0.2, isbinaryfile@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" - integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw== - dependencies: - buffer-alloc "^1.2.0" +isbinaryfile@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.6.tgz#edcb62b224e2b4710830b67498c8e4e5a4d2610b" + integrity sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg== isexe@^2.0.0: version "2.0.0" @@ -8049,6 +8236,16 @@ istanbul-reports@^1.5.1: dependencies: handlebars "^4.0.3" +jake@^10.6.1: + version "10.8.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b" + integrity sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A== + dependencies: + async "0.9.x" + chalk "^2.4.2" + filelist "^1.0.1" + minimatch "^3.0.4" + jest-changed-files@^23.4.2: version "23.4.2" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83" @@ -8411,6 +8608,14 @@ js-yaml@^3.12.0, js-yaml@^3.7.0, js-yaml@^3.9.0: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^3.13.1, js-yaml@^3.14.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -8477,6 +8682,11 @@ json-bigint@^1.0.0: dependencies: bignumber.js "^9.0.0" +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -8526,6 +8736,13 @@ json5@^2.1.0: dependencies: minimist "^1.2.0" +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -8533,6 +8750,15 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" + integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg== + dependencies: + universalify "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -8609,6 +8835,13 @@ keypress@^0.2.1: resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.2.1.tgz#1e80454250018dbad4c3fe94497d6e67b6269c77" integrity sha1-HoBFQlABjbrUw/6USX1uZ7YmnHc= +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + killable@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -8661,18 +8894,23 @@ last-call-webpack-plugin@^3.0.0: lodash "^4.17.5" webpack-sources "^1.1.0" -latest-version@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" - integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU= +latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== dependencies: - package-json "^4.0.0" + package-json "^6.3.0" lazy-val@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc" integrity sha512-pjCf3BYk+uv3ZcPzEVM0BFvO9Uw58TmlrU0oG5tTrr9Kcid3+kdKxapH8CjdYmVa2nO5wOoZn2rdvZx2PKj/xg== +lazy-val@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.4.tgz#882636a7245c2cfe6e0a4e3ba6c5d68a137e5c65" + integrity sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q== + lazystream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" @@ -8924,11 +9162,16 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" -lowercase-keys@^1.0.0: +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + lru-cache@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.6.3.tgz#51ccd0b4fc0c843587d7a5709ce4d3b7629bedc5" @@ -8963,6 +9206,13 @@ make-dir@^1.0.0, make-dir@^1.3.0: dependencies: pify "^3.0.0" +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -9226,16 +9476,26 @@ mime@1.4.1, mime@~1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== -mime@^2.0.3, mime@^2.2.0, mime@^2.3.1, mime@^2.4.0: +mime@^2.0.3, mime@^2.2.0, mime@^2.3.1: version "2.4.0" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.0.tgz#e051fd881358585f3279df333fe694da0bcffdd6" integrity sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w== +mime@^2.4.6: + version "2.4.6" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" + integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA== + mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" @@ -9292,6 +9552,11 @@ minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" @@ -9694,7 +9959,7 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.4.0: +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== @@ -9704,6 +9969,16 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package- semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -9726,6 +10001,11 @@ normalize-url@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== +normalize-url@^4.1.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" + integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== + npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" @@ -10045,6 +10325,11 @@ osenv@0, osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" @@ -10117,15 +10402,15 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ== -package-json@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" - integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0= +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== dependencies: - got "^6.7.1" - registry-auth-token "^3.0.1" - registry-url "^3.0.3" - semver "^5.1.0" + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" pako@^1.0.7, pako@~1.0.5: version "1.0.7" @@ -10159,13 +10444,6 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" -parse-color@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-color/-/parse-color-1.0.0.tgz#7b748b95a83f03f16a94f535e52d7f3d94658619" - integrity sha1-e3SLlag/A/FqlPU15S1/PZRlhhk= - dependencies: - color-convert "~0.5.0" - parse-entities@^1.0.2, parse-entities@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.0.tgz#9deac087661b2e36814153cb78d7e54a4c5fd6f4" @@ -10427,15 +10705,6 @@ please-upgrade-node@^3.1.1: dependencies: semver-compare "^1.0.0" -plist@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" - integrity sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ== - dependencies: - base64-js "^1.2.3" - xmlbuilder "^9.0.7" - xmldom "0.1.x" - plugin-error@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" @@ -10896,10 +11165,10 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= preserve@^0.2.0: version "0.2.0" @@ -11103,6 +11372,13 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +pupa@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726" + integrity sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA== + dependencies: + escape-goat "^2.0.0" + q@^1.1.2, q@~1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -11197,7 +11473,7 @@ raw-body@2.3.3: iconv-lite "0.4.23" unpipe "1.0.0" -rc@^1.0.1, rc@^1.1.6, rc@^1.2.1, rc@^1.2.7: +rc@^1.2.1, rc@^1.2.7, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -11300,20 +11576,16 @@ react@^16.6.3: prop-types "^15.6.2" scheduler "^0.12.0" -read-config-file@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-3.2.0.tgz#50a2756a9a128ab9dcbe087e2724c512e3d0ccd1" - integrity sha512-i1QRc5jy4sHm9YBGb6ArA5SU1mDrc5wu2mnm3r9gPnm+LVZhBGbpTCKqAXyvV4TJHnBR3Yaaww+9b3DyRZcfww== +read-config-file@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-6.0.0.tgz#224b5dca6a5bdc1fb19e63f89f342680efdb9299" + integrity sha512-PHjROSdpceKUmqS06wqwP92VrM46PZSTubmNIMJ5DrMwg1OgenSTSEHIkCa6TiOJ+y/J0xnG1fFwG3M+Oi1aNA== dependencies: - ajv "^6.5.5" - ajv-keywords "^3.2.0" - bluebird-lst "^1.0.6" - dotenv "^6.1.0" - dotenv-expand "^4.2.0" - fs-extra-p "^7.0.0" - js-yaml "^3.12.0" - json5 "^2.1.0" - lazy-val "^1.0.3" + dotenv "^8.2.0" + dotenv-expand "^5.1.0" + js-yaml "^3.13.1" + json5 "^2.1.2" + lazy-val "^1.0.4" read-file-relative@^1.2.0: version "1.2.0" @@ -11570,20 +11842,19 @@ regexpu-core@^4.1.3, regexpu-core@^4.2.0: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.0.2" -registry-auth-token@^3.0.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" - integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ== +registry-auth-token@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.0.tgz#1d37dffda72bbecd0f581e4715540213a65eb7da" + integrity sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w== dependencies: - rc "^1.1.6" - safe-buffer "^5.0.1" + rc "^1.2.8" -registry-url@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== dependencies: - rc "^1.0.1" + rc "^1.2.8" regjsgen@^0.2.0: version "0.2.0" @@ -11812,6 +12083,13 @@ resolve@1.1.7, resolve@~1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= +resolve@^1.10.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.9.0.tgz#a14c6fdfa8f92a7df1d996cb7105fa744658ea06" @@ -11819,6 +12097,13 @@ resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.9.0: dependencies: path-parse "^1.0.6" +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -11958,13 +12243,20 @@ sane@^2.0.0: optionalDependencies: fsevents "^1.2.3" -sanitize-filename@^1.6.0, sanitize-filename@^1.6.1: +sanitize-filename@^1.6.0: version "1.6.1" resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.1.tgz#612da1c96473fa02dccda92dcd5b4ab164a6772a" integrity sha1-YS2hyWRz+gLczaktzVtKsWSmdyo= dependencies: truncate-utf8-bytes "^1.0.0" +sanitize-filename@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" + integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== + dependencies: + truncate-utf8-bytes "^1.0.0" + sass-graph@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" @@ -12067,14 +12359,14 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= -semver-diff@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" - integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= +semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" + integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== dependencies: - semver "^5.0.3" + semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== @@ -12084,7 +12376,7 @@ semver@5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@^6.2.0: +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -12354,6 +12646,14 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" +source-map-support@^0.5.19: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@^0.5.5, source-map-support@^0.5.6, source-map-support@^0.5.9, source-map-support@~0.5.6: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" @@ -12539,10 +12839,10 @@ stackframe@^0.3.1: resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-0.3.1.tgz#33aa84f1177a5548c8935533cbfeb3420975f5a4" integrity sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ= -stat-mode@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" - integrity sha1-5sgLYjEj19gM8TLOU480YokHJQI= +stat-mode@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465" + integrity sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg== state-toggle@^1.0.0: version "1.0.1" @@ -12643,7 +12943,16 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^4.1.0, string-width@^4.2.0: +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== @@ -12711,6 +13020,13 @@ strip-ansi@^5.0.0: dependencies: ansi-regex "^4.0.0" +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -12902,6 +13218,13 @@ supports-color@^6.0.0: dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + supports-color@~5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.0.1.tgz#1c5331f22250c84202805b2f17adf16699f3a39a" @@ -13023,21 +13346,18 @@ teeny-request@^3.11.3: node-fetch "^2.2.0" uuid "^3.3.2" -temp-file@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/temp-file/-/temp-file-3.3.2.tgz#69b6daf1bbe23231d0a5d03844e3d96f3f531aaa" - integrity sha512-FGKccAW0Mux9hC/2bdUIe4bJRv4OyVo4RpVcuplFird1V/YoplIFbnPZjfzbJSf/qNvRZIRB9/4n/RkI0GziuQ== +temp-file@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/temp-file/-/temp-file-3.3.7.tgz#686885d635f872748e384e871855958470aeb18a" + integrity sha512-9tBJKt7GZAQt/Rg0QzVWA8Am8c1EFl+CAv04/aBVqlx5oyfQ508sFIABshQ0xbZu6mBrFLWIUXO/bbLYghW70g== dependencies: async-exit-hook "^2.0.1" - bluebird-lst "^1.0.6" - fs-extra-p "^7.0.0" + fs-extra "^8.1.0" -term-size@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" - integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= - dependencies: - execa "^0.7.0" +term-size@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" + integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== terser-webpack-plugin@^1.1.0: version "1.2.1" @@ -13337,11 +13657,6 @@ time-stamp@^1.0.0: resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= -timed-out@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - timeout-as-promise@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/timeout-as-promise/-/timeout-as-promise-1.0.0.tgz#7367e811fc992acfcdcdaabf2e50dfaf8b21576f" @@ -13405,6 +13720,11 @@ to-object-path@^0.3.0: dependencies: kind-of "^3.0.2" +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" @@ -13555,6 +13875,11 @@ type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + type-is@~1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" @@ -13687,6 +14012,13 @@ unique-string@^1.0.0: dependencies: crypto-random-string "^1.0.0" +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + unist-util-find-all-after@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-1.0.2.tgz#9be49cfbae5ca1566b27536670a92836bf2f8d6d" @@ -13730,6 +14062,11 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" + integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -13748,31 +14085,29 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -unzip-response@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" - integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= - upath@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== -update-notifier@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" - integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw== +update-notifier@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.1.tgz#895fc8562bbe666179500f9f2cebac4f26323746" + integrity sha512-9y+Kds0+LoLG6yN802wVXoIfxYEwh3FlZwzMwpCZp62S2i1/Jzeqb9Eeeju3NSHccGGasfGlK5/vEHbAifYRDg== dependencies: - boxen "^1.2.1" - chalk "^2.0.1" - configstore "^3.0.0" + boxen "^4.2.0" + chalk "^3.0.0" + configstore "^5.0.1" + has-yarn "^2.1.0" import-lazy "^2.1.0" - is-ci "^1.0.10" - is-installed-globally "^0.1.0" - is-npm "^1.0.0" - latest-version "^3.0.0" - semver-diff "^2.0.0" - xdg-basedir "^3.0.0" + is-ci "^2.0.0" + is-installed-globally "^0.3.1" + is-npm "^4.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + pupa "^2.0.1" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" uri-js@^4.2.2: version "4.2.2" @@ -13795,12 +14130,12 @@ url-loader@^1.1.2: mime "^2.0.3" schema-utils "^1.0.0" -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= dependencies: - prepend-http "^1.0.1" + prepend-http "^2.0.0" url-parse@^1.4.3: version "1.4.4" @@ -14285,12 +14620,12 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" -widest-line@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" - integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== dependencies: - string-width "^2.1.1" + string-width "^4.0.0" wordwrap@~0.0.2: version "0.0.3" @@ -14348,6 +14683,16 @@ write-file-atomic@^2.0.0, write-file-atomic@^2.1.0: imurmurhash "^0.1.4" signal-exit "^3.0.2" +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" @@ -14395,21 +14740,16 @@ xdg-basedir@^3.0.0: resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== -xmlbuilder@^9.0.7: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= - -xmldom@0.1.x: - version "0.1.27" - resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" - integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk= - xmlhttprequest@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" @@ -14535,7 +14875,7 @@ yargs@^11.0.0: y18n "^3.2.1" yargs-parser "^9.0.2" -yargs@^12.0.1, yargs@^12.0.4, yargs@^12.0.5: +yargs@^12.0.1, yargs@^12.0.4: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== From a30bf452ab8d31d9256bfcd8edf99caeaf7a5b33 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 4 Nov 2020 17:44:33 -0800 Subject: [PATCH 62/87] Add CI to generate packages with latest dolphin --- .github/workflows/build.yml | 88 +++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..2f9df2fdc --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,88 @@ +name: Release Builds + +on: + push: + branches: + - master + - CI + paths-ignore: + - "**.md" + - "**.ini" + +jobs: + package: + name: Build and package on node ${{ matrix.node-version }} and ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + node-version: [10.x] + os: [ubuntu-latest, windows-latest, macOS-latest] + include: + - os: windows-latest + playback_image: windows64-playback + playback_dolphin_path: app/dolphin-dev/windows/ + - os: ubuntu-latest + playback_image: linux-playback + playback_dolphin_path: app/dolphin-dev/linux/ + - os: macOS-latest + playback_image: macOS-playback + playback_dolphin_path: app/dolphin-dev/osx/ + steps: + - name: Use Node.js ${{ matrix.node-version }} on ${{ matrix.os }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: Checkout + uses: actions/checkout@v2.3.1 + - name: Fetch Git Tags + if: success() + shell: bash + run: | + git fetch --prune --unshallow + echo ::set-env name=GIT_BRANCH::$(git rev-parse --abbrev-ref HEAD) + echo ::set-env name=GIT_HASH::$(git rev-parse --short HEAD) + echo ::set-env name=GIT_TAG::$(git describe --tags --abbrev=0) + - name: Cache node modules + uses: actions/cache@v1 + id: cache + with: + path: node_modules + key: ${{ runner.OS }}-build-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.OS }}-build-${{ env.cache-name }}- + ${{ runner.OS }}-build- + ${{ runner.OS }}- + - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: | + yarn install + - name: Download playback artifact + uses: dawidd6/action-download-artifact@v2 + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: pr-build.yml + branch: slippi + name: ${{ matrix.playback_image }} + path: ${{ matrix.playback_dolphin_path }} + repo: project-slippi/Ishiiruka + - name: Unzip + shell: bash + working-directory: ${{ matrix.playback_dolphin_path }} + run: | + unzip * + rm *.zip + - name: Package + shell: bash + working-directory: ${{ github.workspace }} + run: | + yarn package + mkdir artifact + cp ./release/Slippi* ./artifact + - name: Publish + if: success() + uses: actions/upload-artifact@v2-preview + with: + name: ${{ matrix.os }} + path: "./artifact/" + \ No newline at end of file diff --git a/package.json b/package.json index 5c7676256..a8ddb8605 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "package-ci": "yarn postinstall && yarn build && electron-builder --publish always", "package-linux": "yarn build && electron-builder build --linux", "package-win": "yarn build && electron-builder build --win --x64", - "postinstall": "electron-builder install-app-deps package.json && yarn build-dll", + "postinstall": "electron-builder install-app-deps && yarn build-dll", "postlint-fix": "prettier --ignore-path .eslintignore --single-quote --write '**/*.{*{js,jsx,json},babelrc,eslintrc,prettierrc,stylelintrc}'", "postlint-styles-fix": "prettier --ignore-path .eslintignore --single-quote --write '**/*.{css,scss}'", "prestart": "yarn build", From 6513556703cbb8050fdae36f6302feeb4cdccfb5 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 4 Nov 2020 19:34:09 -0800 Subject: [PATCH 63/87] update copy dolphin script --- internals/scripts/CopyDolphin.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internals/scripts/CopyDolphin.js b/internals/scripts/CopyDolphin.js index d6d85d3b5..1dc8d1aad 100644 --- a/internals/scripts/CopyDolphin.js +++ b/internals/scripts/CopyDolphin.js @@ -28,14 +28,14 @@ function CopyDolphin() { } function copyForMac(targetFolder) { - const dolphinSource = './app/dolphin-dev/osx/Dolphin.app'; + const dolphinSource = './app/dolphin-dev/osx/Slippi Dolphin.app'; if (!fs.existsSync(dolphinSource)) { throw new Error( - 'Must have a Dolphin.app application in dolphin-dev/osx folder.' + 'Must have a Slippi Dolphin.app application in dolphin-dev/osx folder.' ); } - const dolphinDest = path.join(targetFolder, 'Dolphin.app'); + const dolphinDest = path.join(targetFolder, 'Slippi Dolphin.app'); const dolphinDestUserFolder = path.join( dolphinDest, 'Contents/Resources/User' From b4bfa2d6a60df5d69bdb55e2eb4b531f89ed9b2e Mon Sep 17 00:00:00 2001 From: Vince Au Date: Sun, 8 Nov 2020 21:22:46 +1100 Subject: [PATCH 64/87] Fix packaging by disabling hard links --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2f9df2fdc..116322522 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -79,6 +79,8 @@ jobs: yarn package mkdir artifact cp ./release/Slippi* ./artifact + env: + USE_HARD_LINKS: false - name: Publish if: success() uses: actions/upload-artifact@v2-preview From af66517b38b09874d3e6bd9202c23f4c8f28e114 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Sun, 8 Nov 2020 21:40:45 +1100 Subject: [PATCH 65/87] Stop using vulnerable and deprecated set-env command. See: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/ --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 116322522..244d3b1ae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,9 +40,9 @@ jobs: shell: bash run: | git fetch --prune --unshallow - echo ::set-env name=GIT_BRANCH::$(git rev-parse --abbrev-ref HEAD) - echo ::set-env name=GIT_HASH::$(git rev-parse --short HEAD) - echo ::set-env name=GIT_TAG::$(git describe --tags --abbrev=0) + echo "GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)" >> $GITHUB_ENV + echo "GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + echo "GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV - name: Cache node modules uses: actions/cache@v1 id: cache From e4bb5dbe11a468ea4b680f8cb8012cefc75f3198 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Sun, 8 Nov 2020 10:16:06 -0800 Subject: [PATCH 66/87] use Slippi Dolphin.app everywhere --- app/domain/DolphinManager.js | 4 ++-- app/main.dev.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/domain/DolphinManager.js b/app/domain/DolphinManager.js index 4a863f4e7..a7ba11eb3 100644 --- a/app/domain/DolphinManager.js +++ b/app/domain/DolphinManager.js @@ -104,7 +104,7 @@ export default class DolphinManager extends EventEmitter { // Handle the dolphin INI file being in different paths per platform switch (platform) { case "darwin": // osx - dolphinPath = isDev ? "./app/dolphin-dev/osx/Dolphin.app/Contents/Resources/User" : path.join(dolphinPath, "Dolphin.app", "Contents", "Resources", "User"); + dolphinPath = isDev ? "./app/dolphin-dev/osx/Slippi Dolphin.app/Contents/Resources/User" : path.join(dolphinPath, "Slippi Dolphin.app", "Contents", "Resources", "User"); break; case "win32": // windows dolphinPath = isDev ? "./app/dolphin-dev/windows/User" : path.join(dolphinPath, "User"); @@ -219,7 +219,7 @@ export default class DolphinManager extends EventEmitter { switch (platform) { case "darwin": // osx dolphinPath = isDev ? "./app/dolphin-dev/osx" : dolphinPath; - executablePath = path.join(dolphinPath, "Dolphin.app/Contents/MacOS/Dolphin"); + executablePath = path.join(dolphinPath, "Slippi Dolphin.app/Contents/MacOS/Slippi Dolphin"); break; case "win32": // windows dolphinPath = isDev ? "./app/dolphin-dev/windows" : dolphinPath; diff --git a/app/main.dev.js b/app/main.dev.js index c4f6d1b97..ff18cfe8d 100644 --- a/app/main.dev.js +++ b/app/main.dev.js @@ -171,7 +171,7 @@ const handlePreloadLogic = async () => { // Handle the dolphin INI file being in different paths per platform switch (platform) { case "darwin": // osx - dolphinPath = isDev ? "./app/dolphin-dev/osx/Dolphin.app/Contents/Resources/User" : path.join(dolphinPath, "Dolphin.app", "Contents", "Resources", "User"); + dolphinPath = isDev ? "./app/dolphin-dev/osx/Slippi Dolphin.app/Contents/Resources/User" : path.join(dolphinPath, "Slippi Dolphin.app", "Contents", "Resources", "User"); break; case "win32": // windows dolphinPath = isDev ? "./app/dolphin-dev/windows/User" : path.join(dolphinPath, "User"); From dac04bce77e3e855fb071ab155aa6e8babd6900d Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Tue, 17 Nov 2020 10:05:34 -0800 Subject: [PATCH 67/87] Update gecko codes --- .../overwrite/Sys/GameSettings/GALE01r2.ini | 50 ++++++++++-------- .../overwrite/Sys/GameSettings/GALJ01r2.ini | 50 ++++++++++-------- .../overwrite/User/Config/Logger.ini | 7 --- .../User/Config/Profiles/GCPad/B0XX.ini | 25 --------- .../overwrite/User/Config/WiimoteNew.ini | 10 ---- app/dolphin-dev/overwrite/User/GC/SRAM.raw | Bin 64 -> 0 bytes .../overwrite/User/GameSettings/GALE01.ini | 10 ---- .../overwrite/User/GameSettings/GALJ01r2.ini | 10 ---- .../overwrite/User/Wii/shared2/sys/SYSCONF | Bin 16384 -> 0 bytes .../User/Wii/shared2/wc24/mbox/Readme.txt | 4 -- .../User/Wii/shared2/wc24/mbox/wc24recv.ctl | Bin 32768 -> 0 bytes .../User/Wii/shared2/wc24/mbox/wc24recv.mbx | Bin 48 -> 0 bytes .../User/Wii/shared2/wc24/mbox/wc24send.ctl | Bin 16384 -> 0 bytes .../User/Wii/shared2/wc24/mbox/wc24send.mbx | Bin 48 -> 0 bytes .../overwrite/User/Wii/shared2/wc24/misc.bin | Bin 1024 -> 0 bytes .../User/Wii/shared2/wc24/nwc24dl.bin | Bin 63488 -> 0 bytes .../User/Wii/shared2/wc24/nwc24fl.bin | Bin 32864 -> 0 bytes .../User/Wii/shared2/wc24/nwc24fls.bin | Bin 12800 -> 0 bytes .../User/Wii/shared2/wc24/nwc24msg.cbk | Bin 1024 -> 0 bytes .../User/Wii/shared2/wc24/nwc24msg.cfg | Bin 1024 -> 0 bytes 20 files changed, 54 insertions(+), 112 deletions(-) delete mode 100644 app/dolphin-dev/overwrite/User/Config/Logger.ini delete mode 100644 app/dolphin-dev/overwrite/User/Config/Profiles/GCPad/B0XX.ini delete mode 100644 app/dolphin-dev/overwrite/User/Config/WiimoteNew.ini delete mode 100644 app/dolphin-dev/overwrite/User/GC/SRAM.raw delete mode 100644 app/dolphin-dev/overwrite/User/GameSettings/GALE01.ini delete mode 100644 app/dolphin-dev/overwrite/User/GameSettings/GALJ01r2.ini delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/sys/SYSCONF delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/Readme.txt delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24recv.ctl delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24recv.mbx delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24send.ctl delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24send.mbx delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/wc24/misc.bin delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/wc24/nwc24dl.bin delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/wc24/nwc24fl.bin delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/wc24/nwc24fls.bin delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/wc24/nwc24msg.cbk delete mode 100644 app/dolphin-dev/overwrite/User/Wii/shared2/wc24/nwc24msg.cfg diff --git a/app/dolphin-dev/overwrite/Sys/GameSettings/GALE01r2.ini b/app/dolphin-dev/overwrite/Sys/GameSettings/GALE01r2.ini index d98c81d81..43311043e 100644 --- a/app/dolphin-dev/overwrite/Sys/GameSettings/GALE01r2.ini +++ b/app/dolphin-dev/overwrite/Sys/GameSettings/GALE01r2.ini @@ -81,14 +81,14 @@ BE810008 806DB64C BA810008 800100B4 382100B0 7C0803A6 881F0008 00000000 -C206B0DC 00000043 #Playback/Core/RestoreGameFrame.asm +C206B0DC 00000046 #Playback/Core/RestoreGameFrame.asm 7C0802A6 90010004 9421FF50 BE810008 8BBF000C 7FA3EB78 3D808003 618C1724 7D8903A6 4E800421 -7C7C1B78 806DB64C -83630000 7FE3FB78 +7C7C1B78 832DB64C +83790000 7FE3FB78 3D808000 618C55F8 7D8903A6 4E800421 7C741B78 389B0007 @@ -102,18 +102,21 @@ C206B0DC 00000043 #Playback/Core/RestoreGameFrame.asm 807A0010 907F063C 807A0014 907F0650 807A0018 907F065C -807A001C 907F00B0 -807A0020 907F00B4 -807A0024 907F002C -807A0028 907F0010 -3C608046 6063B108 -3C80804C 60841F78 -88840001 3884FFFF -2C040000 40A00008 -38840005 1C840030 -7C632214 889F0618 -1C84000C 7E832214 -887A002C 98740002 +8879056F 2C030000 +41820024 807A001C +907F00B0 807A0020 +907F00B4 807A0024 +907F002C 807A0028 +907F0010 3C608046 +6063B108 3C80804C +60841F78 88840001 +3884FFFF 2C040000 +40A00008 38840005 +1C840030 7C632214 +889F0618 1C84000C +7E832214 887A002C +98740002 8879056F +2C030000 4182004C 807A002D 2C03FFFF 41820040 90610040 C0210040 C05F1830 @@ -149,16 +152,16 @@ D0230030 3D808002 800100B4 382100B0 7C0803A6 881F2219 60000000 00000000 -C216E74C 00000099 #Playback/Core/RestoreGameInfo.asm +C216E74C 0000009A #Playback/Core/RestoreGameInfo.asm 7C0802A6 90010004 9421FF50 BE810008 -3860056F 3D808037 +38600570 3D808037 618CF1E4 7D8903A6 4E800421 7C7C1B78 -938DB64C 3880056F +938DB64C 38800570 3D808000 618CC160 7D8903A6 4E800421 -386001A4 3D808037 +386001A5 3D808037 618CF1E4 7D8903A6 4E800421 7C7E1B78 93DC0000 38600040 @@ -172,7 +175,7 @@ C216E74C 00000099 #Playback/Core/RestoreGameInfo.asm 3880000D 38A00001 3D808000 618C55F0 7D8903A6 4E800421 -7FC3F378 388001A4 +7FC3F378 388001A5 38A00000 3D808000 618C55F0 7D8903A6 4E800421 887E0000 @@ -216,7 +219,8 @@ C216E74C 00000099 #Playback/Core/RestoreGameInfo.asm 4180FF70 887E019D 9862F234 887E019E 9862F238 887E019F -9862F23C 807E01A0 +9862F23C 887E01A0 +987C056F 807E01A1 3D808037 618CF1E4 7D8903A6 4E800421 7C7D1B78 93BC0008 @@ -225,7 +229,7 @@ C216E74C 00000099 #Playback/Core/RestoreGameInfo.asm 38A00001 3D808000 618C55F0 7D8903A6 4E800421 7FA3EB78 -809E01A0 38A00000 +809E01A1 38A00000 3D808000 618C55F0 7D8903A6 4E800421 38800004 909C000C @@ -281,7 +285,7 @@ C216E74C 00000099 #Playback/Core/RestoreGameInfo.asm 7C0803A6 4E800020 38600000 809C0014 90640000 7FA3EB78 -809E01A0 3D808032 +809E01A1 3D808032 618C8F50 7D8903A6 4E800421 38600004 38800007 38A00000 diff --git a/app/dolphin-dev/overwrite/Sys/GameSettings/GALJ01r2.ini b/app/dolphin-dev/overwrite/Sys/GameSettings/GALJ01r2.ini index 9b3992327..1385b3c3a 100644 --- a/app/dolphin-dev/overwrite/Sys/GameSettings/GALJ01r2.ini +++ b/app/dolphin-dev/overwrite/Sys/GameSettings/GALJ01r2.ini @@ -81,14 +81,14 @@ BE810008 806DB64C BA810008 800100B4 382100B0 7C0803A6 881F0008 00000000 -C206B0DC 00000043 #Playback/Core/RestoreGameFrame.asm +C206B0DC 00000046 #Playback/Core/RestoreGameFrame.asm 7C0802A6 90010004 9421FF50 BE810008 8BBF000C 7FA3EB78 3D808003 618C1724 7D8903A6 4E800421 -7C7C1B78 806DB64C -83630000 7FE3FB78 +7C7C1B78 832DB64C +83790000 7FE3FB78 3D808000 618C55F8 7D8903A6 4E800421 7C741B78 389B0007 @@ -102,18 +102,21 @@ C206B0DC 00000043 #Playback/Core/RestoreGameFrame.asm 807A0010 907F063C 807A0014 907F0650 807A0018 907F065C -807A001C 907F00B0 -807A0020 907F00B4 -807A0024 907F002C -807A0028 907F0010 -3C608046 6063B108 -3C80804C 60841F78 -88840001 3884FFFF -2C040000 40A00008 -38840005 1C840030 -7C632214 889F0618 -1C84000C 7E832214 -887A002C 98740002 +8879056F 2C030000 +41820024 807A001C +907F00B0 807A0020 +907F00B4 807A0024 +907F002C 807A0028 +907F0010 3C608046 +6063B108 3C80804C +60841F78 88840001 +3884FFFF 2C040000 +40A00008 38840005 +1C840030 7C632214 +889F0618 1C84000C +7E832214 887A002C +98740002 8879056F +2C030000 4182004C 807A002D 2C03FFFF 41820040 90610040 C0210040 C05F1830 @@ -149,16 +152,16 @@ D0230030 3D808002 800100B4 382100B0 7C0803A6 881F2219 60000000 00000000 -C216E74C 00000099 #Playback/Core/RestoreGameInfo.asm +C216E74C 0000009A #Playback/Core/RestoreGameInfo.asm 7C0802A6 90010004 9421FF50 BE810008 -3860056F 3D808037 +38600570 3D808037 618CF1E4 7D8903A6 4E800421 7C7C1B78 -938DB64C 3880056F +938DB64C 38800570 3D808000 618CC160 7D8903A6 4E800421 -386001A4 3D808037 +386001A5 3D808037 618CF1E4 7D8903A6 4E800421 7C7E1B78 93DC0000 38600040 @@ -172,7 +175,7 @@ C216E74C 00000099 #Playback/Core/RestoreGameInfo.asm 3880000D 38A00001 3D808000 618C55F0 7D8903A6 4E800421 -7FC3F378 388001A4 +7FC3F378 388001A5 38A00000 3D808000 618C55F0 7D8903A6 4E800421 887E0000 @@ -216,7 +219,8 @@ C216E74C 00000099 #Playback/Core/RestoreGameInfo.asm 4180FF70 887E019D 9862F234 887E019E 9862F238 887E019F -9862F23C 807E01A0 +9862F23C 887E01A0 +987C056F 807E01A1 3D808037 618CF1E4 7D8903A6 4E800421 7C7D1B78 93BC0008 @@ -225,7 +229,7 @@ C216E74C 00000099 #Playback/Core/RestoreGameInfo.asm 38A00001 3D808000 618C55F0 7D8903A6 4E800421 7FA3EB78 -809E01A0 38A00000 +809E01A1 38A00000 3D808000 618C55F0 7D8903A6 4E800421 38800004 909C000C @@ -281,7 +285,7 @@ C216E74C 00000099 #Playback/Core/RestoreGameInfo.asm 7C0803A6 4E800020 38600000 809C0014 90640000 7FA3EB78 -809E01A0 3D808032 +809E01A1 3D808032 618C8F50 7D8903A6 4E800421 38600004 38800007 38A00000 diff --git a/app/dolphin-dev/overwrite/User/Config/Logger.ini b/app/dolphin-dev/overwrite/User/Config/Logger.ini deleted file mode 100644 index 2014a2934..000000000 --- a/app/dolphin-dev/overwrite/User/Config/Logger.ini +++ /dev/null @@ -1,7 +0,0 @@ -[LogWindow] -x = 400 -y = 600 -pos = 2 -[Options] -Font = 0 -WrapLines = False diff --git a/app/dolphin-dev/overwrite/User/Config/Profiles/GCPad/B0XX.ini b/app/dolphin-dev/overwrite/User/Config/Profiles/GCPad/B0XX.ini deleted file mode 100644 index 73a55ee1e..000000000 --- a/app/dolphin-dev/overwrite/User/Config/Profiles/GCPad/B0XX.ini +++ /dev/null @@ -1,25 +0,0 @@ -[Profile] -Device = DInput/0/Arduino Leonardo -Buttons/A = `Button 0` -Buttons/B = `Button 1` -Buttons/X = `Button 2` -Buttons/Y = `Button 3` -Buttons/Z = `Button 4` -Buttons/Start = `Button 7` -Main Stick/Up = `Axis Y+` -Main Stick/Down = `Axis Y-` -Main Stick/Left = `Axis X-` -Main Stick/Right = `Axis X+` -C-Stick/Up = `Axis Yr+` -C-Stick/Down = `Axis Yr-` -C-Stick/Left = `Axis Xr-` -C-Stick/Right = `Axis Xr+` -Triggers/Threshold = 0.00000000000000000 -Triggers/L = `Button 5` -Triggers/R = `Button 6` -Triggers/L-Analog = `Slider 0-+` -Triggers/R-Analog = `Button 6` -D-Pad/Up = `Button 9` -D-Pad/Down = `Button 11` -D-Pad/Left = `Button 8` -D-Pad/Right = `Button 10` diff --git a/app/dolphin-dev/overwrite/User/Config/WiimoteNew.ini b/app/dolphin-dev/overwrite/User/Config/WiimoteNew.ini deleted file mode 100644 index 8609bf8f7..000000000 --- a/app/dolphin-dev/overwrite/User/Config/WiimoteNew.ini +++ /dev/null @@ -1,10 +0,0 @@ -[Wiimote1] -Source = 0 -[Wiimote2] -Source = 0 -[Wiimote3] -Source = 0 -[Wiimote4] -Source = 0 -[BalanceBoard] -Source = 0 diff --git a/app/dolphin-dev/overwrite/User/GC/SRAM.raw b/app/dolphin-dev/overwrite/User/GC/SRAM.raw deleted file mode 100644 index 79e3642db34a19e42052f3146ce48d885f78ae73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64 jcmZS3`G0`{73jG5`viD+`UU&=hd3g!oluqK<%0MCZkY-u diff --git a/app/dolphin-dev/overwrite/User/GameSettings/GALE01.ini b/app/dolphin-dev/overwrite/User/GameSettings/GALE01.ini deleted file mode 100644 index 5a134ad1a..000000000 --- a/app/dolphin-dev/overwrite/User/GameSettings/GALE01.ini +++ /dev/null @@ -1,10 +0,0 @@ -[Core] -CPUThread = False -GPUDeterminismMode = fake-completion -PollingMethod = OnSIRead -FastDiscSpeed = True -[Gecko_Enabled] -$Required: General Codes -$Required: Slippi Playback -$Recommended: Normal Lag Reduction -[Gecko] diff --git a/app/dolphin-dev/overwrite/User/GameSettings/GALJ01r2.ini b/app/dolphin-dev/overwrite/User/GameSettings/GALJ01r2.ini deleted file mode 100644 index 5a134ad1a..000000000 --- a/app/dolphin-dev/overwrite/User/GameSettings/GALJ01r2.ini +++ /dev/null @@ -1,10 +0,0 @@ -[Core] -CPUThread = False -GPUDeterminismMode = fake-completion -PollingMethod = OnSIRead -FastDiscSpeed = True -[Gecko_Enabled] -$Required: General Codes -$Required: Slippi Playback -$Recommended: Normal Lag Reduction -[Gecko] diff --git a/app/dolphin-dev/overwrite/User/Wii/shared2/sys/SYSCONF b/app/dolphin-dev/overwrite/User/Wii/shared2/sys/SYSCONF deleted file mode 100644 index 975709619c8db7995556905559b902fffff969f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeI$&ui0Q7zgktU8r-2ZlhW1Po~Hm;=;QjLp%s=lGd;^3w^Uz27+QUEl4Z6A2_`F zANU7&(2C$qJ?!AYi&sHBco6a6CJMWX$PT{mo3Ya_gVG%KeM_6SN&7r`K6y#Y!|i28 z$LWgxQh%#|*1zgM^iBPbanQ&aCylo8$ari%F`t^R%s1vc^Mm=({9=ALH_gBKOnx9g zGFFT%#|ujO4V~!W(accLY%RvEMtihc^C#>enqZT(m!WkfN~SAO`nnQjFV*9-5P-n$ z0v&Oy;cmdi(Y}%w`c~l07}TIP-KBeUhnm#d{$e(khYM9L7GEif?Sg#Id5zS>56ap( zwWr`z2Ms|4b+*NRvrpH* zrNS{!TjIXkRKLP$oIv{dmr}0(U&{HD`frQBvuTX9uYVdfBPRqP00ALz`gL~rxoip8 z#Un$x&Vp<;gfq2kuG|;e9_hI*IlTzn$g-o*mhm>~^}1E%5y>{H?Rce(=%Qlmdx4Hz zc3vRYNWYqws&YQQu9m2yZ6w>Nq_H&@Mj6%E3d=m{aJkb=Q#~-}Dyaomw@YOaKr5-h zj<1pSQ%>DEzo5EgmDx!9RSA7=Rc33RtL^(s000O;00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00IzzK(_@h(8B diff --git a/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/Readme.txt b/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/Readme.txt deleted file mode 100644 index 6813fc73c..000000000 --- a/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/Readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -The Mailbox here has been shrunk, the real file size: - -WC24RECV.MBX 0x00700000 -WC24SEND.MBX 0x00200000 diff --git a/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24recv.ctl b/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24recv.ctl deleted file mode 100644 index a4880f368a10aa41b749d2692ee2c644c1c85e79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32768 zcmc(gX;)5B7={m-h0J8A%(IXT87uQlWS%05%1p-lFZxBulHT{c)86Oo{ak0QmilNJeIi)m~q#+n36$OV#G3%!x(7Nkx@? zF-i8!LgM7Y0(jR6fEFOf{|pOSrq3xd#g)LOmUL_zQ)SCb)25{x#`QEA15>!^soJ`n zE^A^j&;S3~;`_YS4CPJ8cRw@VdG70(${mp_U{^#Q-Zf7e%NREj5 z9Je7(>lGp;d&ZpXr$H{~C`e4^khz&J!yL|4n4GLB^RgZWx|^p!K^bEjGTwzcYfz}9 zY&r9@odvs^uV7J`f)-@D3U{`miit9-e0P~fu3>8JoiJdFH`75zr5vs>%q5|D|n<=V58S| z_~k~0&-6)L;j%HPYZNcrC3&sOQpBCLiWu$? zz0P4L=E^$7Os}22zV=GgjrEEeUo(6|&5gJV8x%LcR{F+T3z6p=6&X+?ep8Kk?C~bW zCRESgTzwpUx>?Z?RRLS7PU8=^C_bYaVQaOa!ECDxAXO0Cs?01#+hjqh%-CLeWHQ+< z6HGr>U1pbFT#^RG>Vt;|-EIv67`**_rov?ow?B50Z zcfT3z{{-xR681j{`=5gSPr?4DVgJ*x{~6f-4D5dv_CE{zpM(9+!T#rA|MRf_ z1=#-r?0*sVzX3j1G!{jb6PJ+OZd?0+5hzYhD~ zfc_85 z*#80S{}A?n2>U;R{U5>pk757Euzw%y-v|3Yf&HJr{!d~5r?7uN?B5UjKZE_B!T!%- z|L3s(0PH^i`wznYgRuV#*#8CW{}T3p3HuMh{zI_;Fzi1J`;Wl>Be4G~*#8ym{~Gpx z4g0@={ola;Z(;wpu>U*Q{~hfA9`=6^`+tD_KfwMUVgHY?|0mf06YM_<`;Wr@pJD&c lu>Tj>{|oH@754uM`+tM|zrp_BVgK*2{}0&z2kdXJ{~I9Hj!^&r diff --git a/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24recv.mbx b/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24recv.mbx deleted file mode 100644 index 81cd383a972c35377f86e6a6b70a4fc8a2c514ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48 ecmWG@b5r>DpOJx~fPsNQ0f^DShyNge5Cj10GzokF diff --git a/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24send.ctl b/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24send.ctl deleted file mode 100644 index 165daf72b357f44cd8aec3e329cef2409edad4bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmc)J+cLsY6bImcA&DY7A1FoVqo`E!5N14p8Lz>klf#WGZhUKIt+lWAZ@xXVADq^!`ZOb>#vjSs@uzlHr<*#G?v)iZ2k z|Bixx@Q>gDfXXY{~7k5VSfetE7)Jf{wnsLWB)n!*Ra2a{dMfG zWB&#AUts?w_FrOu1N$4;-^BhV_P4OVh5c>pZ)1N4`#ad*#r`h#_prZ*{eA53WB&mA z2iQNv{vq~{uz!U8W9%Pe{}uLMVgCgCC)j_D{nyxkgZ($yKgIqj_Rp|?hW&HwpJV?m j_TOUv0{a)(zr_9}_OGyih5dKfe~0~R>|bO5|MTAf{th{5 diff --git a/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24send.mbx b/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/mbox/wc24send.mbx deleted file mode 100644 index d4474476feac95f8461e3d10720242275402f1f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48 ecmWG@b5r>DpOJwtiQ~Z& zGx`rW9S@!yPh6eh=!tR0i_SQD_k=gSSbxtZr3C8yN=%IW`0mV;&9nR6m+$wpFV8-^ zlg{9*VHk=^ZP;O~GcGPw+CLu39m^@})DOy<`27-X?&kW!3Y#Cw9UmjTQdZB}Lae{F zzP!HgZdu>;71uYc*GJnweC4xPpKn{Qm+M;l`O80k-El(qZHRjQAl zJWBP^Pn9)3x?Df|iLU=l^D!U+B!C2v02270BydUZhraL9NVfwL@vr`Oy?cRv8wQp6 z`b5Ko4pd4}R5@sx&U7g`Z&xbGdCyBaLD{r@Ke*sKu9@n~nrSngJn#7im1O7@eOI>@ zFx-}aG8Xi-)$+e>`3_82CI1ZguL4eDaTOv+#3sbYVr{}cEo9mtUUqAonT{|kd)y8{3I==W%2UXXx!zjK2bYd4#_f|M{4|x<>s#OYQ%J>M|A==|a)HpsbUIvUY8z za+=ELRIbsxkM+tL{))yQQ~8$4pUT>^Pg#36()b%HzbPx1SJud{wdM0)C@cSyvW7NM znWS=ASv!kVzNGTY4fFr-r_SGZ=flP$U@k-5KKd|-XX)ObyMCy3VzjX>y8+k#yZ#{g zHwNzS(%1M6`n_iD`F|i6U;iC_ws$WW4TC=a_huRD3(DwU>^$sWk2vzct#EPUwOWzQL)o?^E;<@!^jBOTcPJK5y8Q!WhJk=?di z+5?HJv_HgutbYF=tKI*n45dol3oG>hEPpF-Cq`PRt@AH?o)h?yOWiyTuK_ZteJ0JA zitKQvw{5w#&`+mU6@z@R>nd%3js9+d&i{D4)c(`_X-1S__IzhJt&we8@~ha_0B1N;Tk<*n@me?BC^ie2C@m@aQ^ zH~8}*30CX@f5CKlYtMo|ACh225BLkF%UgR6{P~asE1m~`!E||RFMvNEl3>MN@E1&% zxAr3V^C1aVyafJ&>GIZI27f*z!HOjK3#Q9kGr^w^Nw6XX{(|Z9*3#h5ha^~$0e``C zd21H<^C1aVWWirBUEbP0@aIDktmp-Q!E||R`@x?NNwDGo_zR}XTk8XVJ|w}4gWxZi zE^qA>@aIDktT+Vzg6Zly1ca<`12tNRt$i@ zV7k1uqu|enBv>&B{(|Z9){cQcACh3jaqt&Rm$#M&e?BC^iXre9OqaKI0{r=q1S^KY zUoc(X+H2s?ha^}r0{(*O^43m*KOd4{#VGg-rpsG<9sK!_1S`hCUoc(X+8f}{ha^}r z4*r7a^42E6pASi};uQD`rpsG94gP#cf)!`LUoc(X+9de%AqiHz3I2lV^489RKOd4{ z#arMnm@aSaZSdzq60A4}{(|Z9*4_bsJ|w}4cfnsUUEbOh`12tNR=fxPg6Z1%?`v&4&|Adddc~@KsH$*z{ADK(J?I`w=$|I%-byk z-4LTR0|Qe_6EhPF)3lV76mw(q6iZ9<6bl10<5VLP3qz3ljFOUqVk>?9#N2Yd@?;|u zJ*b=XlhZSGlQQ%46O)tkOY=(ffP8fGslf-?546508He@B8L7$Hw6Yw@|G6bN98i>+ uoSIpdN-HP8!XKyoDXBTBB{Z`h9{)J)FHX%%p_S*Uk$?ud84J0xE&%`q=3<2a diff --git a/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/nwc24msg.cfg b/app/dolphin-dev/overwrite/User/Wii/shared2/wc24/nwc24msg.cfg deleted file mode 100644 index c87fb77301d3cb2ed345ebd406acb268f88a0588..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmWGfc1~kpVBlbo=KU{p{!<>1%?`v&4&|Adddc~@KsH$*z{ADK(J?I`w=$|I%-byk z-4LTR0|Qe_6EhPF)3lV76mw(q6iZ9<6bl10<5VLP3qz3ljFOUqVk>?9#N2Yd@?;|u zJ*b=XlhZSGlQQ%46O)tkOY=(ffP8fGslf-?546508He@B8L7$Hw6Yw@|G6bN98i>+ uoSIpdN-HP8!XKyoDXBTBB{Z`h9{)J)FHX%%p_S*Uk$?ud84J0xE&%`q=3<2a From e4521884c004bfd4e7d37163d7970e3fad344a6a Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Tue, 17 Nov 2020 18:15:54 -0800 Subject: [PATCH 68/87] update build.yml --- .github/workflows/build.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 244d3b1ae..8948a06fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,9 +2,6 @@ name: Release Builds on: push: - branches: - - master - - CI paths-ignore: - "**.md" - "**.ini" @@ -60,7 +57,7 @@ jobs: - name: Download playback artifact uses: dawidd6/action-download-artifact@v2 with: - github_token: ${{secrets.GITHUB_TOKEN}} + github_token: ${{ secrets.GITHUB_TOKEN }} workflow: pr-build.yml branch: slippi name: ${{ matrix.playback_image }} @@ -76,6 +73,7 @@ jobs: shell: bash working-directory: ${{ github.workspace }} run: | + echo ${{ secrets.ENVFILE }} > .env yarn package mkdir artifact cp ./release/Slippi* ./artifact From 68c947842f52db42e459d41c87fe401997f112d2 Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Mon, 23 Nov 2020 16:45:47 -0800 Subject: [PATCH 69/87] backup more events for longer disconnects --- app/domain/BroadcastManager.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index bbadd5416..fd0504e54 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -12,6 +12,10 @@ import { displayError } from '../actions/error'; const SLIPPI_WS_SERVER = process.env.SLIPPI_WS_SERVER; +// This variable defines the number of events saved in the case of a disconnect. 1800 should +// support disconnects of 30 seconds at most +const BACKUP_MAX_LENGTH = 1800; + /** * Responsible for retrieving Dolphin game data over enet and sending the data * to the Slippi server over websockets. @@ -210,11 +214,22 @@ export class BroadcastManager { // Add any events that didn't make it to the server to the front of the event queue const backedEventsToUse = _.filter(this.backupEvents, event => { const isNeededByServer = event.cursor > obj.recoveryGameCursor; + + // Make sure we aren't duplicating anything that is already in the incoming events array const isNotIncoming = _.isNil(firstCursor) || event.cursor < firstCursor; + return isNeededByServer && isNotIncoming; }); - log.info(backedEventsToUse); + this.incomingEvents = _.concat(backedEventsToUse, this.incomingEvents); + + const newFirstEvent = _.first(this.incomingEvents) || {}; + const newFirstCursor = newFirstEvent.cursor; + + const firstBackupCursor = (_.first(this.backupEvents) || {}).cursor; + const lastBackupCursor = (_.last(this.backupEvents) || {}).cursor; + + log.info(`[Broadcast] Backup events include range from: [${firstBackupCursor}, ${lastBackupCursor}]. Next cursor to be sent: ${newFirstCursor}`); } connectionComplete(obj.broadcastId); @@ -296,7 +311,7 @@ export class BroadcastManager { const event = this.incomingEvents.shift(); this.backupEvents.push(event); - if (this.backupEvents.length > 100) { + if (this.backupEvents.length > BACKUP_MAX_LENGTH) { // Remove element after adding one once size is too big this.backupEvents.shift(); } From 79dbfd7633611ba65d5548c002cb61991874fda3 Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Tue, 24 Nov 2020 18:53:26 -0800 Subject: [PATCH 70/87] improve broadcasting ui --- app/actions/broadcast.js | 12 +-- app/components/Broadcast.js | 129 ++++++++++++++++++++++++++------- app/components/Broadcast.scss | 75 ++++++++----------- app/domain/BroadcastManager.js | 6 +- app/domain/SpectateManager.js | 5 +- 5 files changed, 144 insertions(+), 83 deletions(-) diff --git a/app/actions/broadcast.js b/app/actions/broadcast.js index dd5027b66..ea4fb316d 100644 --- a/app/actions/broadcast.js +++ b/app/actions/broadcast.js @@ -35,9 +35,9 @@ export function updateViewableBroadcasts(broadcasts) { }; } -export function startBroadcast(password) { +export function startBroadcast(target) { return async () => { - await broadcastManager.start(password); + await broadcastManager.start(target); }; } @@ -47,10 +47,10 @@ export function stopBroadcast() { }; } -export function refreshBroadcasts(password) { +export function refreshBroadcasts() { return async () => { try { - await spectateManager.connect(password); + await spectateManager.connect(); spectateManager.refreshBroadcasts(); } catch { // Do nothing @@ -64,10 +64,10 @@ export function watchBroadcast(broadcastId) { }; } -export function initSpectate(password) { +export function initSpectate() { return async () => { try { - await spectateManager.connect(password); + await spectateManager.connect(); } catch { // Do nothing } diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 996bb4d19..3cce36962 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -3,12 +3,16 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import _ from 'lodash'; +import * as firebase from 'firebase'; +import classNames from 'classnames'; import { - Button, Header, Segment, Icon, Tab, Input, + Button, Header, Segment, Icon, Tab, Input, List, } from 'semantic-ui-react'; import { Link } from 'react-router-dom'; +import { ConnectionStatus } from '@slippi/slippi-js'; + import PageHeader from './common/PageHeader'; import PageWrapper from './PageWrapper'; import DismissibleMessage from './common/DismissibleMessage'; @@ -36,7 +40,7 @@ export default class Broadcast extends Component { }; state = { - password: "", + viewerId: "", } renderGlobalError() { @@ -67,7 +71,7 @@ export default class Broadcast extends Component { if (active) { this.props.stopBroadcast(); } else { - this.props.startBroadcast(this.state.password); + this.props.startBroadcast(this.state.viewerId); } }; return ( @@ -86,7 +90,7 @@ export default class Broadcast extends Component { @@ -95,6 +99,23 @@ export default class Broadcast extends Component { renderBroadcasts() { const broadcasts = _.get(this.props.broadcast, 'broadcasts') || []; + if (_.isEmpty(broadcasts)) { + return ( +
+ + + No broadcasts found + + Click refresh to reload + + +
+ ) + } const broadcastEntries = _.map(broadcasts, broadcast => { const name = _.get(broadcast, 'name'); const broadcasterName = _.get(broadcast, ['broadcaster', 'name']); @@ -148,20 +169,73 @@ export default class Broadcast extends Component { ); } + renderStatusDisplay(status, prefix) { + let statusMsg = `${prefix}Disconnected`; + let statusColor = "gray"; + if (status === ConnectionStatus.CONNECTED) { + statusMsg = `${prefix}Connected`; + statusColor = "green"; + } else if (status === ConnectionStatus.CONNECTING) { + statusMsg = `${prefix}Connecting...`; + statusColor = "yellow"; + } else if (status === ConnectionStatus.RECONNECT_WAIT) { + statusMsg = `${prefix}Reconnecting...`; + statusColor = "yellow"; + } + + const valueClasses = classNames({ + [styles['conn-status-value']]: true, + [styles['green']]: statusColor === "green", + [styles['gray']]: statusColor === "gray", + [styles['yellow']]: statusColor === "yellow", + [styles['white']]: statusColor === "white", + }); + + return ( + + + {statusMsg} + + ); + } + renderBroadcastContent() { - const { slippiConnectionStatus, dolphinConnectionStatus, startTime, endTime, isConnecting, isBroadcasting } = this.props.broadcast; + const { slippiConnectionStatus, dolphinConnectionStatus, startTime, endTime, isBroadcasting } = this.props.broadcast; + + return (
-

Broadcast

+ + + + Open Slippi Dolphin and start game + + + + Enter the ID from whoever will be viewing your broadcast + + + + Click Start Broadcast + + + { + this.setState({ + viewerId: p.value, + }); + }} + /> {this.renderButton()}
-
Status: {isBroadcasting ? `broadcasting since ${JSON.stringify(startTime)}` : endTime ? `broadcast lasted ${(endTime - startTime) / 1000} seconds` : "not broadcasting"}
-
dolphin connection status: {JSON.stringify(dolphinConnectionStatus)}
-
slippi connection status: {JSON.stringify(slippiConnectionStatus)}
-
isBroadcasting: {JSON.stringify(isBroadcasting)}
-
isConnecting: {JSON.stringify(isConnecting)}
+
Status: {isBroadcasting ? `Broadcasting since ${JSON.stringify(startTime)}` : endTime ? `Broadcast lasted ${(endTime - startTime) / 1000} seconds` : "Not broadcasting"}
+ {this.renderStatusDisplay(dolphinConnectionStatus, "Dolphin ")} + {this.renderStatusDisplay(slippiConnectionStatus, "Broadcast ")}
@@ -169,9 +243,24 @@ export default class Broadcast extends Component { } renderSpectateContent() { + const user = firebase.auth().currentUser; + return (
-

Spectate

+ + + + Give the person broadcasting your ID: {user.uid} + + + + After they have started their broadcast, refresh + + + + Once the broadcast appears, click to watch + + {this.renderRefreshButton()} {this.renderBroadcasts()}
@@ -199,21 +288,6 @@ export default class Broadcast extends Component { ); } - renderPasswordInput() { - return ( - { - this.setState({ - password: p.value, - }); - }} - /> - ); - } - renderContent() { const { user } = this.props.auth; if (!user) { @@ -223,7 +297,6 @@ export default class Broadcast extends Component { return (
{this.renderGlobalError()} - {this.renderPasswordInput()} {this.renderTabs()}
); diff --git a/app/components/Broadcast.scss b/app/components/Broadcast.scss index a73401e15..880f28ccd 100644 --- a/app/components/Broadcast.scss +++ b/app/components/Broadcast.scss @@ -6,65 +6,48 @@ margin-right: auto; } +.highlight { + color: $foreground; +} + .tabs { margin-top: 24px; :global(.menu) { - border-color: rgba(255, 255, 255, 0.2) !important; + // border-color: rgba(255, 255, 255, 0.2) !important; + border-bottom-width: 0 !important; + a { + color: rgba(255, 255, 255, 0.7) !important; + font-size: 20px; + font-weight: lighter !important; + border-bottom-color: $primary-gray !important; + border-bottom-width: 4px !important; + + } + + :global(.active) { color: $foreground !important; + font-weight: bolder !important; + border-bottom-color: $primary-green !important; } } -} - -.section { - margin-bottom: 48px; -} - -.global-action-section { - margin-bottom: 15px; -} - -.card { - box-shadow: 3px 3px 2px rgba(0, 0, 0, 0.1) !important; - background: none !important; - border-style: solid !important; - border-width: 1px !important; - border-color: $background-darkest !important; - color: $foreground; - margin: 0 !important; - .content { - border-color: $background-darkest !important; - background-color: $background-light !important; + h2 { + color: rgba(255, 255, 255, 0.9); } - .warning-bar { - border-color: $background-darkest !important; - background-color: $primary-yellow !important; - padding-top: 4px !important; - padding-bottom: 5px !important; - color: black; - font-weight: 700; + div { + color: rgba(255, 255, 255, 0.7); } } -.label { - font-weight: bold; - color: rgba(255, 255, 255, 0.5); - margin-right: 4px; -} - -.conn-content-grid { - display: grid; - grid-template-columns: auto 1fr; - grid-column-gap: 6px; +.section { + margin-bottom: 48px; } -.conn-button-grid { - display: grid; - grid-template-columns: auto auto 1fr auto auto; - grid-column-gap: 3px; +.global-action-section { + margin-bottom: 15px; } .conn-status-value { @@ -87,6 +70,12 @@ } } +.label { + font-weight: bold; + color: rgba(255, 255, 255, 0.5); + margin-right: 4px; +} + .description { color: gray; // Move label margin to be under the description diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index fd0504e54..06479546a 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -78,7 +78,7 @@ export class BroadcastManager { /** * Connects to the Slippi server and the local Dolphin instance */ - async start(password) { + async start(target) { if (this.wsConnection) { // We're already connected return; @@ -88,7 +88,7 @@ export class BroadcastManager { store.dispatch(setSlippiStatus(ConnectionStatus.CONNECTING)); const headers = { - password: password, + target: target, "api-version": 1, }; const user = firebase.auth().currentUser; @@ -183,7 +183,7 @@ export class BroadcastManager { if (code === 1006) { // Here we have an abnormal disconnect... try to reconnect? - this.start(password); + this.start(target); } else { // If normal close, disconnect from dolphin this.dolphinConnection.disconnect(); diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index a24dd00e3..12fa753a9 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -132,7 +132,7 @@ export class SpectateManager { /** * Connects to the Slippi server and the local Dolphin instance */ - async connect(password) { + async connect() { if (this.wsConnection) { // We're already connected console.log("Skipping websocket connection since we're already connected"); @@ -140,7 +140,6 @@ export class SpectateManager { } const headers = { - password: password, "api-version": 1, }; const user = firebase.auth().currentUser; @@ -183,7 +182,7 @@ export class SpectateManager { if (code === 1006) { // Here we have an abnormal disconnect... try to reconnect? - this.connect(password).then(() => { + this.connect().then(() => { if (!this.prevBroadcastId || !this.wsConnection) { return; } From 1a4a307ce4c0d1f43f66091e66fa565de6b11183 Mon Sep 17 00:00:00 2001 From: Jas Laferriere Date: Wed, 25 Nov 2020 13:41:27 -0800 Subject: [PATCH 71/87] improve broadcast list UI --- app/components/Broadcast.js | 54 ++++++++++++++++++++++++---------- app/components/Broadcast.scss | 44 +++++++++++++++++++++++++++ app/domain/BroadcastManager.js | 2 +- app/domain/SpectateManager.js | 2 +- 4 files changed, 84 insertions(+), 18 deletions(-) diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 3cce36962..058fcb54c 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -7,7 +7,7 @@ import * as firebase from 'firebase'; import classNames from 'classnames'; import { - Button, Header, Segment, Icon, Tab, Input, List, + Button, Header, Segment, Icon, Tab, Input, List, Card, } from 'semantic-ui-react'; import { Link } from 'react-router-dom'; @@ -92,6 +92,7 @@ export default class Broadcast extends Component { size="large" onClick={() => this.props.refreshBroadcasts()} > + Refresh ); @@ -120,23 +121,46 @@ export default class Broadcast extends Component { const name = _.get(broadcast, 'name'); const broadcasterName = _.get(broadcast, ['broadcaster', 'name']); return ( - -
[{broadcasterName}] {name} ({broadcast.id})
- -
+ + +
+ {this.renderLabelValue("Broadcaster", broadcasterName)} + {this.renderLabelValue("Name", name)} + {/* {this.renderLabelValue("ID", broadcast.id)} */} +
+
+ +
+ +
+
+
); }); return ( -
+ {broadcastEntries} -
+ + ); + } + + renderLabelValue(label, value) { + return ( + +
{label}
+
{value}
+
); } @@ -202,8 +226,6 @@ export default class Broadcast extends Component { renderBroadcastContent() { const { slippiConnectionStatus, dolphinConnectionStatus, startTime, endTime, isBroadcasting } = this.props.broadcast; - - return (
@@ -232,7 +254,7 @@ export default class Broadcast extends Component { }} /> {this.renderButton()} -
+
Status: {isBroadcasting ? `Broadcasting since ${JSON.stringify(startTime)}` : endTime ? `Broadcast lasted ${(endTime - startTime) / 1000} seconds` : "Not broadcasting"}
{this.renderStatusDisplay(dolphinConnectionStatus, "Dolphin ")} {this.renderStatusDisplay(slippiConnectionStatus, "Broadcast ")} diff --git a/app/components/Broadcast.scss b/app/components/Broadcast.scss index 880f28ccd..cad7da8ee 100644 --- a/app/components/Broadcast.scss +++ b/app/components/Broadcast.scss @@ -50,6 +50,42 @@ margin-bottom: 15px; } +.card { + box-shadow: 3px 3px 2px rgba(0, 0, 0, 0.1) !important; + background: none !important; + border-style: solid !important; + border-width: 1px !important; + border-color: $background-darkest !important; + color: $foreground; + margin: 0 !important; + + .content { + border-color: $background-darkest !important; + background-color: $background-light !important; + } + + .warning-bar { + border-color: $background-darkest !important; + background-color: $primary-yellow !important; + padding-top: 4px !important; + padding-bottom: 5px !important; + color: black; + font-weight: 700; + } +} + +.conn-content-grid { + display: grid; + grid-template-columns: auto 1fr; + grid-column-gap: 6px; +} + +.conn-button-grid { + display: grid; + grid-template-columns: auto auto 1fr auto auto; + grid-column-gap: 3px; +} + .conn-status-value { font-weight: bold; @@ -98,4 +134,12 @@ .spacer { padding: 10px; +} + +.connection-details { + margin-top: 6px; +} + +.broadcast-list { + margin-top: 12px; } \ No newline at end of file diff --git a/app/domain/BroadcastManager.js b/app/domain/BroadcastManager.js index 06479546a..5ca167206 100644 --- a/app/domain/BroadcastManager.js +++ b/app/domain/BroadcastManager.js @@ -89,7 +89,7 @@ export class BroadcastManager { const headers = { target: target, - "api-version": 1, + "api-version": 2, }; const user = firebase.auth().currentUser; if (user) { diff --git a/app/domain/SpectateManager.js b/app/domain/SpectateManager.js index 12fa753a9..66970fd3c 100644 --- a/app/domain/SpectateManager.js +++ b/app/domain/SpectateManager.js @@ -140,7 +140,7 @@ export class SpectateManager { } const headers = { - "api-version": 1, + "api-version": 2, }; const user = firebase.auth().currentUser; if (user) { From 3d7cb113eddc19369b17f6c0f7a9ee3f2ee93e4a Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 25 Nov 2020 13:50:03 -0800 Subject: [PATCH 72/87] add yml to artifact so we can actually release --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8948a06fc..c3c3485ae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,8 +3,8 @@ name: Release Builds on: push: paths-ignore: - - "**.md" - - "**.ini" + - '**.md' + - '**.ini' jobs: package: @@ -77,6 +77,7 @@ jobs: yarn package mkdir artifact cp ./release/Slippi* ./artifact + cp ./release/*.yml ./artifact env: USE_HARD_LINKS: false - name: Publish @@ -84,5 +85,4 @@ jobs: uses: actions/upload-artifact@v2-preview with: name: ${{ matrix.os }} - path: "./artifact/" - \ No newline at end of file + path: './artifact/' From 7a1498e6ad32d8c761ce415e33c101dd19770c5e Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 25 Nov 2020 14:01:02 -0800 Subject: [PATCH 73/87] only target dmg on macOS --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index a8ddb8605..c08118345 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,6 @@ }, "category": "your.app.category.type", "target": [ - "zip", "dmg" ] }, From 1ba9f46c7846ae45904a95c097d98370dd4dd815 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Wed, 25 Nov 2020 19:48:25 -0800 Subject: [PATCH 74/87] Signing and notarizing the desktop app for macOS (#98) --- .github/workflows/build.yml | 14 +++++++++++ build/afterSignHook.macos.js | 43 ++++++++++++++++++++++++++++++++++ build/entitlements.macos.plist | 16 +++++++++++++ build/load-macos-certs-ci.sh | 28 ++++++++++++++++++++++ package.json | 9 ++++--- 5 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 build/afterSignHook.macos.js create mode 100644 build/entitlements.macos.plist create mode 100644 build/load-macos-certs-ci.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c3c3485ae..81fecd635 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,6 +50,20 @@ jobs: ${{ runner.OS }}-build-${{ env.cache-name }}- ${{ runner.OS }}-build- ${{ runner.OS }}- + - name: Load macOS signing certificates and secrets + if: matrix.os == 'macOS-latest' && env.CERTIFICATE_MACOS_PASSWORD != null + run: | + chmod +x build/load-macos-certs-ci.sh && ./build/load-macos-certs-ci.sh + mkdir -p ~/private_keys/ + echo '${{ secrets.APPLE_CONNECT_API_KEY }}' > ~/private_keys/AuthKey_${{ secrets.APPLE_API_KEY_ID }}.p8 + echo "CSC_LINK=${{ secrets.CERTIFICATE_MACOS_APPLICATION }}" >> $GITHUB_ENV + echo "CSC_KEY_PASSWORD=${{ secrets.CERTIFICATE_MACOS_PASSWORD }}" >> $GITHUB_ENV + echo "APPLE_API_KEY=${{ secrets.APPLE_API_KEY_ID }}" >> $GITHUB_ENV + echo "APPLE_ISSUER_ID=${{ secrets.APPLE_ISSUER_ID }}" >> $GITHUB_ENV + echo "APPLE_TEAM_PROVIDER_ID=${{ secrets.APPLE_TEAM_PROVIDER_ID }}" >> $GITHUB_ENV + env: + CERTIFICATE_MACOS_APPLICATION: ${{ secrets.CERTIFICATE_MACOS_APPLICATION }} + CERTIFICATE_MACOS_PASSWORD: ${{ secrets.CERTIFICATE_MACOS_PASSWORD }} - name: Install dependencies if: steps.cache.outputs.cache-hit != 'true' run: | diff --git a/build/afterSignHook.macos.js b/build/afterSignHook.macos.js new file mode 100644 index 000000000..1c6183467 --- /dev/null +++ b/build/afterSignHook.macos.js @@ -0,0 +1,43 @@ +const fs = require('fs'); +const path = require('path'); +var electron_notarize = require('electron-notarize'); + +module.exports = async function (params) { + if(process.platform !== 'darwin') { + return; + } + + console.log('afterSign hook triggered', params); + + // Bail early if this is a fork-caused PR build, which doesn't get + // secrets. + if( + !process.env.APPLE_TEAM_PROVIDER_ID || + !process.env.APPLE_API_KEY || + !process.env.APPLE_ISSUER_ID + ) { + console.log("Bailing, no secrets found."); + return; + } + + let appId = 'com.github.projectslippi.slippidesktopapp'; + let appPath = path.join(params.appOutDir, `${params.packager.appInfo.productFilename}.app`); + if (!fs.existsSync(appPath)) { + throw new Error(`Cannot find application at: ${appPath}`); + } + + console.log(`Notarizing ${appId} found at ${appPath} (this could take awhile, get some coffee...)`); + + try { + await electron_notarize.notarize({ + appBundleId: appId, + appPath: appPath, + appleApiKey: process.env.APPLE_API_KEY, + appleApiIssuer: process.env.APPLE_ISSUER_ID, + }); + + console.log(`Successfully notarized ${appId}`); + } catch (error) { + console.error(error); + } +}; diff --git a/build/entitlements.macos.plist b/build/entitlements.macos.plist new file mode 100644 index 000000000..e2e590d54 --- /dev/null +++ b/build/entitlements.macos.plist @@ -0,0 +1,16 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.cs.disable-executable-page-protection + + com.apple.security.automation.apple-events + + + diff --git a/build/load-macos-certs-ci.sh b/build/load-macos-certs-ci.sh new file mode 100644 index 000000000..8d0035317 --- /dev/null +++ b/build/load-macos-certs-ci.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env sh + +KEY_CHAIN=build.keychain +CERTIFICATE_P12=certificate.p12 + +# Recreate the certificate from the secure environment variable +echo $CERTIFICATE_MACOS_APPLICATION | base64 --decode > $CERTIFICATE_P12 + +# Create a temporary keychain +security create-keychain -p actions $KEY_CHAIN + +# Remove the relock timeout, which can happen if our builds take forever. +security set-keychain-settings $KEY_CHAIN + +# Import certificate +security import $CERTIFICATE_P12 -k $KEY_CHAIN -P $CERTIFICATE_MACOS_PASSWORD -T /usr/bin/codesign; + +# Mark this as okay to be accessed from command line tools +security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k actions $KEY_CHAIN + +# Make the keychain the default so identities are found +security default-keychain -s $KEY_CHAIN + +# Unlock the keychain +security unlock-keychain -p actions $KEY_CHAIN + +# remove certs +rm -fr *.p12 diff --git a/package.json b/package.json index c08118345..698544b61 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "build": { "productName": "Slippi Launcher", "appId": "com.github.projectslippi.slippidesktopapp", + "afterSign": "./build/afterSignHook.macos.js", "asarUnpack": [ "**/dolphin/**/*", "**/images/**/*", @@ -81,7 +82,9 @@ "role": "viewer", "icon": "./resources/file.icns" }, - "category": "your.app.category.type", + "hardenedRuntime": true, + "entitlements": "./build/entitlements.macos.plist", + "category": "public.app-category.video", "target": [ "dmg" ] @@ -204,6 +207,7 @@ "electron": "^4.1.4", "electron-builder": "^22.8.0", "electron-devtools-installer": "^2.2.4", + "electron-notarize": "^1.0.0", "enzyme": "^3.7.0", "enzyme-adapter-react-16": "^1.7.0", "enzyme-to-json": "^3.3.4", @@ -261,7 +265,6 @@ "electron-debug": "^2.0.0", "electron-log": "^2.2.17", "electron-settings": "^3.2.0", - "electron-sudo": "^4.0.12", "electron-updater": "^4.0.6", "firebase": "^7.20.0", "fs-extra": "^8.1.0", @@ -297,4 +300,4 @@ "pre-commit": "yarn lint --quiet" } } -} \ No newline at end of file +} From 83101259aec794af4d207e724c4d20759765750b Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Tue, 6 Oct 2020 18:31:54 -0700 Subject: [PATCH 75/87] Add ledgegrab count to actions in stats --- app/components/stats/OverallTable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/stats/OverallTable.js b/app/components/stats/OverallTable.js index 1003615b5..3f1cf14ba 100644 --- a/app/components/stats/OverallTable.js +++ b/app/components/stats/OverallTable.js @@ -296,9 +296,9 @@ export default class OverallTable extends Component { this.renderOpeningField('Counter Hits', 'counterHitRatio'), this.renderOpeningField('Beneficial Trades', 'beneficialTradeRatio'), this.renderMultiStatField( - 'Actions (Wavedash / Waveland / Dash Dance)', + 'Actions (Wavedash / Waveland / Dash Dance / Ledgegrab)', ['actionCounts'], - ['wavedashCount', 'wavelandCount', 'dashDanceCount'] + ['wavedashCount', 'wavelandCount', 'dashDanceCount', 'ledgegrabCount'] ), ]; } From 5323bee36dd8d6d8a541c3f07ff4734933557e89 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 21 Oct 2020 22:27:22 -0700 Subject: [PATCH 76/87] add Digital Inputs / Minute --- app/components/stats/OverallTable.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/components/stats/OverallTable.js b/app/components/stats/OverallTable.js index 3f1cf14ba..ce4d4522f 100644 --- a/app/components/stats/OverallTable.js +++ b/app/components/stats/OverallTable.js @@ -311,6 +311,7 @@ export default class OverallTable extends Component { , this.renderHigherSimpleRatioField('Inputs / Minute', 'inputsPerMinute'), + this.renderHigherSimpleRatioField('Digital Inputs / Minute', 'digitalInputsPerMinute'), ]; } From 176bb00d83c141835ae517775c38921bbe98e8b5 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 25 Nov 2020 20:13:42 -0800 Subject: [PATCH 77/87] always run yarn install --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 81fecd635..2a80e2da0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -65,7 +65,6 @@ jobs: CERTIFICATE_MACOS_APPLICATION: ${{ secrets.CERTIFICATE_MACOS_APPLICATION }} CERTIFICATE_MACOS_PASSWORD: ${{ secrets.CERTIFICATE_MACOS_PASSWORD }} - name: Install dependencies - if: steps.cache.outputs.cache-hit != 'true' run: | yarn install - name: Download playback artifact From b8f970de7cbebbd4af45e5a58e05b5cbd549e12c Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 25 Nov 2020 21:19:02 -0800 Subject: [PATCH 78/87] Update codes --- .../overwrite/Sys/GameSettings/GALE01r2.ini | 16 ++++++++++++++++ .../overwrite/Sys/GameSettings/GALJ01r2.ini | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/app/dolphin-dev/overwrite/Sys/GameSettings/GALE01r2.ini b/app/dolphin-dev/overwrite/Sys/GameSettings/GALE01r2.ini index 43311043e..b2716f17e 100644 --- a/app/dolphin-dev/overwrite/Sys/GameSettings/GALE01r2.ini +++ b/app/dolphin-dev/overwrite/Sys/GameSettings/GALE01r2.ini @@ -836,3 +836,19 @@ $Optional: Enable Develop Mode [UnclePunch] *Turns develop (debug) mode on. Allows access to frame advance, hit/hurtbox display, and alternate camera angles 0415FDBC 480000AC #External/Enable Develop Mode/Enable Develop Mode.asm 04089250 48000008 #External/Enable Develop Mode/Enable Stale Moves.asm + +$Optional: Lagless FoD [Achilles, Myougi, Dan Salvato] +*Disables particles and reflection on FoD to improve performance +C21CBB90 00000005 #Lagless FoD +9421FFF8 3CC0804A +80C6ED78 3CA00002 +60A5AE44 7CA53050 +88C50000 60C60004 +98C50000 00000000 +041CC8AC FC000028 +041CBE9C 60000000 +041CBEF0 60000000 +041CBF54 60000000 +04390838 60000000 +041CD250 60000000 +041CCDCC 480000B4 diff --git a/app/dolphin-dev/overwrite/Sys/GameSettings/GALJ01r2.ini b/app/dolphin-dev/overwrite/Sys/GameSettings/GALJ01r2.ini index 1385b3c3a..86498e9d6 100644 --- a/app/dolphin-dev/overwrite/Sys/GameSettings/GALJ01r2.ini +++ b/app/dolphin-dev/overwrite/Sys/GameSettings/GALJ01r2.ini @@ -836,3 +836,19 @@ $Optional: Enable Develop Mode [UnclePunch] *Turns develop (debug) mode on. Allows access to frame advance, hit/hurtbox display, and alternate camera angles 0415FDBC 480000AC #External/Enable Develop Mode/Enable Develop Mode.asm 04089250 48000008 #External/Enable Develop Mode/Enable Stale Moves.asm + +$Optional: Lagless FoD [Achilles, Myougi, Dan Salvato] +*Disables particles and reflection on FoD to improve performance +C21CBB90 00000005 #Lagless FoD +9421FFF8 3CC0804A +80C6ED78 3CA00002 +60A5AE44 7CA53050 +88C50000 60C60004 +98C50000 00000000 +041CC8AC FC000028 +041CBE9C 60000000 +041CBEF0 60000000 +041CBF54 60000000 +04390838 60000000 +041CD250 60000000 +041CCDCC 480000B4 From 9af087a17efc487ab377ddfb028cc3415608ac37 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 25 Nov 2020 21:20:13 -0800 Subject: [PATCH 79/87] build on ini changes --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2a80e2da0..f34bf282d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,6 @@ on: push: paths-ignore: - '**.md' - - '**.ini' jobs: package: From 3c70710919984035c51ee8a339af2d97ea062411 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 25 Nov 2020 22:27:45 -0800 Subject: [PATCH 80/87] format macOS script --- build/afterSignHook.macos.js | 64 ++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/build/afterSignHook.macos.js b/build/afterSignHook.macos.js index 1c6183467..3e0c68a54 100644 --- a/build/afterSignHook.macos.js +++ b/build/afterSignHook.macos.js @@ -1,43 +1,43 @@ const fs = require('fs'); const path = require('path'); -var electron_notarize = require('electron-notarize'); +const electronNotarize = require('electron-notarize'); module.exports = async function (params) { - if(process.platform !== 'darwin') { - return; - } + if (process.platform !== 'darwin') { + return; + } - console.log('afterSign hook triggered', params); + console.log('afterSign hook triggered', params); - // Bail early if this is a fork-caused PR build, which doesn't get - // secrets. - if( - !process.env.APPLE_TEAM_PROVIDER_ID || - !process.env.APPLE_API_KEY || - !process.env.APPLE_ISSUER_ID - ) { - console.log("Bailing, no secrets found."); - return; - } + // Bail early if this is a fork-caused PR build, which doesn't get + // secrets. + if ( + !process.env.APPLE_TEAM_PROVIDER_ID || + !process.env.APPLE_API_KEY || + !process.env.APPLE_ISSUER_ID + ) { + console.log("Bailing, no secrets found."); + return; + } - let appId = 'com.github.projectslippi.slippidesktopapp'; - let appPath = path.join(params.appOutDir, `${params.packager.appInfo.productFilename}.app`); - if (!fs.existsSync(appPath)) { - throw new Error(`Cannot find application at: ${appPath}`); - } + const appId = 'com.github.projectslippi.slippidesktopapp'; + const appPath = path.join(params.appOutDir, `${params.packager.appInfo.productFilename}.app`); + if (!fs.existsSync(appPath)) { + throw new Error(`Cannot find application at: ${appPath}`); + } - console.log(`Notarizing ${appId} found at ${appPath} (this could take awhile, get some coffee...)`); + console.log(`Notarizing ${appId} found at ${appPath} (this could take awhile, get some coffee...)`); - try { - await electron_notarize.notarize({ - appBundleId: appId, - appPath: appPath, - appleApiKey: process.env.APPLE_API_KEY, - appleApiIssuer: process.env.APPLE_ISSUER_ID, - }); + try { + await electronNotarize.notarize({ + appBundleId: appId, + appPath: appPath, + appleApiKey: process.env.APPLE_API_KEY, + appleApiIssuer: process.env.APPLE_ISSUER_ID, + }); - console.log(`Successfully notarized ${appId}`); - } catch (error) { - console.error(error); - } + console.log(`Successfully notarized ${appId}`); + } catch (error) { + console.error(error); + } }; From fcbfed29540a4537ceedcea07c6a18cc1e2ece43 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Wed, 25 Nov 2020 22:28:05 -0800 Subject: [PATCH 81/87] bump slippi-js to 5.1.0 --- package.json | 2 +- yarn.lock | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 698544b61..c3db5ac9f 100644 --- a/package.json +++ b/package.json @@ -258,7 +258,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^5.5.0", "@google-cloud/storage": "^2.4.2", - "@slippi/slippi-js": "^5.1.0-beta.2", + "@slippi/slippi-js": "^5.1.0", "async-retry": "^1.2.3", "classnames": "^2.2.6", "devtron": "^1.4.0", diff --git a/yarn.lock b/yarn.lock index d9f41ec05..89ceb4cda 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1375,10 +1375,10 @@ array-from "^2.1.1" lodash.get "^4.4.2" -"@slippi/slippi-js@^5.1.0-beta.2": - version "5.1.0-beta.2" - resolved "https://registry.yarnpkg.com/@slippi/slippi-js/-/slippi-js-5.1.0-beta.2.tgz#e8f9ac50f97692d047a884ab73c2b3aff5873f75" - integrity sha512-OACCMaQ/gJROMuMRV2OHSHm76xUJ1mwuZw9sTDFj+Bt3ykex9IQ/3ebZ1qX7i2nWeonB/iDrigvPTTzkjL4q8w== +"@slippi/slippi-js@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@slippi/slippi-js/-/slippi-js-5.1.0.tgz#ec523179d07b48fde94036080c4abd1b6eab4cc4" + integrity sha512-u9RWxFU8oDzv5COCmA2lSnQzcgFwEliFNKijDfzKRlnQ68AuIFz/RFOaP+YwWegvarTYVU29RdDtnD1+oAjlpw== dependencies: "@shelacek/ubjson" "^1.0.1" enet "^0.2.9" @@ -3143,16 +3143,16 @@ bluebird-lst@^1.0.9: dependencies: bluebird "^3.5.5" -bluebird@^3.4.6, bluebird@^3.5.5: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - bluebird@^3.5.1, bluebird@^3.5.2, bluebird@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== +bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -5235,6 +5235,14 @@ electron-log@^2.2.17: resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-2.2.17.tgz#e71e2ebb949fc96ded7cdb99eeee7202e48981d2" integrity sha512-v+Af5W5z99ehhaLOfE9eTSXUwjzh2wFlQjz51dvkZ6ZIrET6OB/zAZPvsuwT6tm3t5x+M1r+Ed3U3xtPZYAyuQ== +electron-notarize@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/electron-notarize/-/electron-notarize-1.0.0.tgz#bc925b1ccc3f79e58e029e8c4706572b01a9fd8f" + integrity sha512-dsib1IAquMn0onCrNMJ6gtEIZn/azG8hZMCYOuZIMVMUeRMgBYHK1s5TK9P8xAcrAjh/2aN5WYHzgVSWX314og== + dependencies: + debug "^4.1.1" + fs-extra "^9.0.1" + electron-publish@22.8.0: version "22.8.0" resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.8.0.tgz#7f410fe043abc5d3d896c4ee9eea7a43ea352c7d" @@ -5257,14 +5265,6 @@ electron-settings@^3.2.0: clone "^2.1.1" jsonfile "^4.0.0" -electron-sudo@^4.0.12: - version "4.0.12" - resolved "https://registry.yarnpkg.com/electron-sudo/-/electron-sudo-4.0.12.tgz#17d27fcb33837b7f6fd3a7946f168d6590566a53" - integrity sha1-F9J/yzODe39v06eUbxaNZZBWalM= - dependencies: - babel-runtime "^6.18.0" - bluebird "^3.4.6" - electron-to-chromium@^1.3.47, electron-to-chromium@^1.3.96: version "1.3.100" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.100.tgz#899fb088def210aee6b838a47655bbb299190e13" From 11889de9088350d94f2f3c665c421b77e9d87202 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Thu, 26 Nov 2020 19:54:28 +1100 Subject: [PATCH 82/87] Add button to copy broadcasting id to clipboard --- app/components/Broadcast.js | 5 ++- app/components/Broadcast.scss | 5 +++ app/components/common/CopyToClipboard.js | 41 ++++++++++++++++++++++++ package.json | 1 + yarn.lock | 34 ++++++++++++++++++++ 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 app/components/common/CopyToClipboard.js diff --git a/app/components/Broadcast.js b/app/components/Broadcast.js index 058fcb54c..56b46a00b 100644 --- a/app/components/Broadcast.js +++ b/app/components/Broadcast.js @@ -13,6 +13,7 @@ import { Link } from 'react-router-dom'; import { ConnectionStatus } from '@slippi/slippi-js'; +import CopyToClipboard from './common/CopyToClipboard'; import PageHeader from './common/PageHeader'; import PageWrapper from './PageWrapper'; import DismissibleMessage from './common/DismissibleMessage'; @@ -272,7 +273,9 @@ export default class Broadcast extends Component { - Give the person broadcasting your ID: {user.uid} + + Give the person broadcasting your ID: {user.uid} + diff --git a/app/components/Broadcast.scss b/app/components/Broadcast.scss index cad7da8ee..9c533513a 100644 --- a/app/components/Broadcast.scss +++ b/app/components/Broadcast.scss @@ -8,6 +8,11 @@ .highlight { color: $foreground; + + cursor: pointer; + &:hover { + text-decoration: underline; + } } .tabs { diff --git a/app/components/common/CopyToClipboard.js b/app/components/common/CopyToClipboard.js new file mode 100644 index 000000000..fa71930bc --- /dev/null +++ b/app/components/common/CopyToClipboard.js @@ -0,0 +1,41 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { Popup } from 'semantic-ui-react'; +import Copy from 'react-copy-to-clipboard'; + +export default class CopyToClipboard extends Component { + static propTypes = { + children: PropTypes.any.isRequired, + timeoutMs: PropTypes.number, + text: PropTypes.string, + }; + + static defaultProps = { + timeoutMs: 2000, + text: '', + }; + + state = { + copied: false, + }; + + onCopy = () => { + this.setState({ copied: true }); + setTimeout(() => this.setState({ copied: false }), this.props.timeoutMs); + }; + + render() { + return ( + this.onCopy()}> + {this.props.children} + + } + /> + ); + } +} diff --git a/package.json b/package.json index c3db5ac9f..b256b2018 100644 --- a/package.json +++ b/package.json @@ -275,6 +275,7 @@ "obs-websocket-js": "^3.0.0", "prop-types": "^15.6.2", "react": "^16.6.3", + "react-copy-to-clipboard": "^5.0.2", "react-dom": "^16.6.3", "react-hot-loader": "^4.3.12", "react-redux": "^5.1.1", diff --git a/yarn.lock b/yarn.lock index 89ceb4cda..8a2bcf6ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4224,6 +4224,13 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= +copy-to-clipboard@^3: + version "3.3.1" + resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" + integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== + dependencies: + toggle-selection "^1.0.6" + core-js@3.6.5: version "3.6.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" @@ -11254,6 +11261,15 @@ prompts@^0.1.9: kleur "^2.0.1" sisteransi "^0.1.1" +prop-types@^15.5.8: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + prop-types@^15.6.1, prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" @@ -11483,6 +11499,14 @@ rc@^1.2.1, rc@^1.2.7, rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-copy-to-clipboard@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.2.tgz#d82a437e081e68dfca3761fbd57dbf2abdda1316" + integrity sha512-/2t5mLMMPuN5GmdXo6TebFa8IoFxZ+KTDDqYhcDm0PhkgEzSxVvIX26G20s1EB02A4h2UZgwtfymZ3lGJm0OLg== + dependencies: + copy-to-clipboard "^3" + prop-types "^15.5.8" + react-dom@^16.6.3: version "16.7.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.7.0.tgz#a17b2a7ca89ee7390bc1ed5eb81783c7461748b8" @@ -11513,6 +11537,11 @@ react-is@^16.3.2, react-is@^16.6.0, react-is@^16.6.1, react-is@^16.7.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.7.0.tgz#c1bd21c64f1f1364c6f70695ec02d69392f41bfa" integrity sha512-Z0VRQdF4NPDoI0tsXVMLkJLiwEBa+RP66g0xDHxgxysxSoCUccSten4RTF/UFvZF1dZvZ9Zu1sx+MDXwcOR34g== +react-is@^16.8.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" @@ -13743,6 +13772,11 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +toggle-selection@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" + integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= + tough-cookie@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" From 377484221c18a441d433fa5d1509a41d754bd80b Mon Sep 17 00:00:00 2001 From: Vince Au Date: Thu, 26 Nov 2020 19:56:02 +1100 Subject: [PATCH 83/87] Update slippi-js version --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b256b2018..4fd8380b6 100644 --- a/package.json +++ b/package.json @@ -258,7 +258,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^5.5.0", "@google-cloud/storage": "^2.4.2", - "@slippi/slippi-js": "^5.1.0", + "@slippi/slippi-js": "^5.1.1", "async-retry": "^1.2.3", "classnames": "^2.2.6", "devtron": "^1.4.0", diff --git a/yarn.lock b/yarn.lock index 8a2bcf6ea..3e5ef1640 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1375,10 +1375,10 @@ array-from "^2.1.1" lodash.get "^4.4.2" -"@slippi/slippi-js@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@slippi/slippi-js/-/slippi-js-5.1.0.tgz#ec523179d07b48fde94036080c4abd1b6eab4cc4" - integrity sha512-u9RWxFU8oDzv5COCmA2lSnQzcgFwEliFNKijDfzKRlnQ68AuIFz/RFOaP+YwWegvarTYVU29RdDtnD1+oAjlpw== +"@slippi/slippi-js@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@slippi/slippi-js/-/slippi-js-5.1.1.tgz#63dc0ba131019fcaf9fe01417c6ecbe53db095aa" + integrity sha512-5iutrhwfjQNA2Ri9vzWM30wsAY43MVzSWT/hW/CkqS3jEU/I8PIpn5kMVLz2gESYnYOjOSTCB4sqEQJBLrBBSA== dependencies: "@shelacek/ubjson" "^1.0.1" enet "^0.2.9" From c26e334cba16a6f3f482cdac385c425fc7c04492 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Thu, 26 Nov 2020 19:57:11 +1100 Subject: [PATCH 84/87] Clipboard text should be required --- app/components/common/CopyToClipboard.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/components/common/CopyToClipboard.js b/app/components/common/CopyToClipboard.js index fa71930bc..bb5598fbe 100644 --- a/app/components/common/CopyToClipboard.js +++ b/app/components/common/CopyToClipboard.js @@ -6,13 +6,12 @@ import Copy from 'react-copy-to-clipboard'; export default class CopyToClipboard extends Component { static propTypes = { children: PropTypes.any.isRequired, + text: PropTypes.string.isRequired, timeoutMs: PropTypes.number, - text: PropTypes.string, }; static defaultProps = { timeoutMs: 2000, - text: '', }; state = { From 04df191f71be5ad5b4744db3ced9b451d9a0a456 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Thu, 26 Nov 2020 20:00:46 +1100 Subject: [PATCH 85/87] Change copy message to 'Copy to clipboard' --- app/components/common/CopyToClipboard.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/components/common/CopyToClipboard.js b/app/components/common/CopyToClipboard.js index bb5598fbe..727e9ee28 100644 --- a/app/components/common/CopyToClipboard.js +++ b/app/components/common/CopyToClipboard.js @@ -26,11 +26,11 @@ export default class CopyToClipboard extends Component { render() { return ( this.onCopy()}> + {this.props.children} } From 31fd601fdb5f963dd8abea2f04d3a837f7d3bfa7 Mon Sep 17 00:00:00 2001 From: Vince Au Date: Thu, 26 Nov 2020 21:23:01 +1100 Subject: [PATCH 86/87] Reset clipboard timeout on unmount --- app/components/common/CopyToClipboard.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/components/common/CopyToClipboard.js b/app/components/common/CopyToClipboard.js index 727e9ee28..1b4b45be6 100644 --- a/app/components/common/CopyToClipboard.js +++ b/app/components/common/CopyToClipboard.js @@ -18,17 +18,29 @@ export default class CopyToClipboard extends Component { copied: false, }; + timeout = null; + onCopy = () => { + this.reset(); this.setState({ copied: true }); - setTimeout(() => this.setState({ copied: false }), this.props.timeoutMs); + this.timeout = setTimeout(() => this.setState({ copied: false }), this.props.timeoutMs); }; + reset = () => { + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + this.setState({ copied: false }); + } + render() { return ( {this.props.children} From 311562510fbc6f3b4476aea818b03bd8b33bc1c5 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Thu, 26 Nov 2020 02:38:25 -0800 Subject: [PATCH 87/87] bump to app ver to 1.6.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4fd8380b6..d6ba209e0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "slippi-desktop-app", "productName": "Slippi Desktop App", - "version": "1.5.2-dev.6", + "version": "1.6.0", "description": "Slippi Desktop App for browsing and playing replays.", "scripts": { "build": "concurrently \"yarn build-main\" \"yarn build-renderer\"",