2017-06-08_509bba0/509bba0_unpacked_with_node_modules/discord_app/components/user_settings/UserSettingsGames.js
2022-07-26 10:06:20 -07:00

351 lines
10 KiB
JavaScript
Executable file

import React from 'react';
import Flux from '../../lib/flux';
import lodash from 'lodash';
import Popout from '../common/Popout';
import SwitchItem from '../../uikit/SwitchItem';
import Select from '../../uikit/Select';
import OverlayIconOff from '../../uikit/icons/OverlayIconOff';
import OverlayIconOn from '../../uikit/icons/OverlayIconOn';
import Button, {ButtonSizes, ButtonLooks, ButtonColors} from '../../uikit/Button';
import {FormSection, FormTitleTags, FormTitle, FormDivider} from '../../uikit/form';
import HoverRoll from '../../uikit/HoverRoll';
import EmptyState, {EmptyStateText, EmptyStateImage} from '../../uikit/EmptyState';
import classNames from 'classnames';
import NativeUtils from '../../utils/NativeUtils';
import UserSettingsActionCreators from '../../actions/UserSettingsActionCreators';
import UserSettingsStore from '../../stores/UserSettingsStore';
import RunningGameStore from '../../stores/RunningGameStore';
import GamesActionCreators from '../../actions/GamesActionCreators';
import Tooltip from '../common/Tooltip';
import i18n from '../../i18n';
import '../../styles/user_settings_games.styl';
import '../../styles/round_remove_button.styl';
import '../../styles/shared/hover_card.styl';
import type {RunningGame} from '../../flow/Client';
const ThemedEmptyState = Flux.connectStores([UserSettingsStore], () => ({
theme: UserSettingsStore.theme,
}))(EmptyState);
const enableOverlayToggle = NativeUtils.isWindows();
class AddGamePopout extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
selectedValue: null,
};
lodash.bindAll(this, ['handleGameChange', 'handleAdd', 'handleClose']);
}
render() {
const {candidates} = this.props;
const {selectedValue} = this.state;
const options = candidates.map(candidate => ({value: candidate.pid, label: candidate.name}));
return (
<div className="add-game-popout elevation-border-high">
<Select clearable={false} options={options} onChange={this.handleGameChange} value={selectedValue} />
<FormDivider className="margin-top-8 margin-bottom-8" />
<div className="actions flex-horizontal">
<Button
className="cancel-button"
look={ButtonLooks.LINK}
color={ButtonColors.GREY}
onClick={this.handleClose}>
{i18n.Messages.CANCEL}
</Button>
<Button disabled={selectedValue == null} onClick={this.handleAdd}>
{i18n.Messages.SETTINGS_GAMES_ADD_NEW_GAME}
</Button>
</div>
</div>
);
}
handleGameChange(value) {
this.setState({selectedValue: value});
}
handleAdd() {
GamesActionCreators.addGame(this.state.selectedValue.value);
const {onClose} = this.props;
onClose();
}
handleClose() {
const {onClose} = this.props;
onClose();
}
}
const AddGamePopoutConnected = Flux.connectStores([RunningGameStore], () => {
return {
candidates: RunningGameStore.getCandidateGames(),
};
})(AddGamePopout);
class Game extends React.PureComponent {
constructor(props) {
super(props);
lodash.bindAll(this, [
'handleRemoveClick',
'handleNameEdit',
'handleNameChange',
'handleOverlayToggle',
'handleEnterKey',
]);
this.state = {
editingName: props.game != null ? props.game.gameName : '',
};
}
componentWillReceiveProps(newProps) {
if (this.props.nowPlaying && newProps.game) {
if (newProps.game.gameName !== this.state.editingName) {
this.setState({editingName: newProps.game.gameName});
}
}
}
renderName() {
const {game} = this.props;
if (game == null) {
return <div className="game-name">{i18n.Messages.SETTINGS_GAMES_NO_GAME_DETECTED}</div>;
}
if (game.verified) {
return (
<div className="flex-horizontal">
<div className="game-name game-name-verified">
{game.gameName}
</div>
<Tooltip text={i18n.Messages.SETTINGS_GAMES_VERIFIED_ICON}>
<i className="game-verified-icon" />
</Tooltip>
</div>
);
}
return (
<input
className="game-name game-name-input"
type="text"
maxLength={128}
value={this.state.editingName}
onBlur={this.handleNameEdit}
onKeyDown={this.handleEnterKey}
onChange={this.handleNameChange}
/>
);
}
renderLastPlayed() {
const {game, nowPlaying} = this.props;
if (game == null) {
return <div className="last-played">{i18n.Messages.SETTINGS_GAMES_NOT_PLAYING}</div>;
}
const {played, exePath} = game;
let lastPlayed;
if (nowPlaying) {
lastPlayed = i18n.Messages.SETTINGS_GAMES_NOW_PLAYING_STATE;
} else if (played) {
lastPlayed = i18n.Messages.SETTINGS_GAMES_LAST_PLAYED.format({when: played});
}
return (
<div className="last-played">
<HoverRoll hoverText={exePath ? exePath.toUpperCase() : ''}>
{lastPlayed}
</HoverRoll>
</div>
);
}
renderOverlayToggle() {
const {game} = this.props;
if (!enableOverlayToggle || game == null) {
return null;
}
const {overlay, overlayWarn} = game;
const text = overlay ? i18n.Messages.SETTINGS_GAMES_OVERLAY_ON : i18n.Messages.SETTINGS_GAMES_OVERLAY_OFF;
const icon = overlay
? <OverlayIconOn className="overlay-toggle-icon-on" />
: <OverlayIconOff className="overlay-toggle-icon-off" />;
const overlayWarning = overlayWarn
? <Tooltip text={i18n.Messages.SETTINGS_GAMES_OVERLAY_WARNING}>
<i className="overlay-warning-icon" />
</Tooltip>
: null;
return (
<div className="flex-center flex-nowrap flex-justify-between">
{overlayWarning}
<div className="overlay-status-text">{text}</div>
<Tooltip text={i18n.Messages.SETTINGS_GAMES_TOGGLE_OVERLAY}>
<div className="overlay-toggle-icon" onClick={this.handleOverlayToggle}>{icon}</div>
</Tooltip>
</div>
);
}
renderRemove() {
return (
<div className="round-remove-button remove-game" onClick={this.handleRemoveClick}>
{i18n.Messages.REMOVE_KEYBIND}
</div>
);
}
render() {
const {nowPlaying, game} = this.props;
const exists = game != null;
const classes = classNames('flex-center', {
game: !nowPlaying,
'ui-hover-card': !nowPlaying,
'now-playing': exists && nowPlaying,
'not-detected': !exists && nowPlaying,
});
return (
<div className={classes}>
<div className="game-name-last-played flex-vertical">
{this.renderName()}
{this.renderLastPlayed()}
</div>
{this.renderOverlayToggle()}
{!nowPlaying && exists ? this.renderRemove() : null}
</div>
);
}
// Handlers
handleRemoveClick() {
GamesActionCreators.deleteEntry(this.props.game);
}
handleNameEdit() {
const {game} = this.props;
const {editingName} = this.state;
if (game.gameName !== editingName) {
GamesActionCreators.editName(game, editingName);
}
}
handleNameChange(event) {
this.setState({editingName: event.target.value});
}
handleEnterKey(event) {
if (event.keyCode == 13) {
event.target.blur();
event.preventDefault();
}
}
handleOverlayToggle() {
GamesActionCreators.toggleOverlay(this.props.game);
}
}
class UserSettingsGames extends React.PureComponent {
props: {
showCurrentGame: boolean,
gameHistory: Array<RunningGame>,
runningGame: RunningGame,
};
componentDidMount() {
RunningGameStore.watchCandidateGames(true);
}
componentWillUnmount() {
RunningGameStore.watchCandidateGames(false);
}
handleChangeCurrentGame(e) {
UserSettingsActionCreators.updateRemoteSettings({showCurrentGame: e.currentTarget.checked});
}
renderPopout(props) {
return <AddGamePopoutConnected {...props} />;
}
renderGameList() {
const {gameHistory} = this.props;
// Empty state message
if (!gameHistory.length) {
return (
<ThemedEmptyState className="margin-top-40">
<EmptyStateImage
darkSrc={require('../../images/empties/empty_user_settings_games_dark.svg')}
lightSrc={require('../../images/empties/empty_user_settings_games_light.svg')}
width={430}
height={250}
/>
<EmptyStateText>
{i18n.Messages.SETTINGS_GAMES_NO_GAMES_HEADER}
</EmptyStateText>
</ThemedEmptyState>
);
} else {
return (
<FormSection className="games-list">
<FormTitle className="margin-bottom-4">{i18n.Messages.SETTINGS_GAMES_ADDED_GAMES_LABEL}</FormTitle>
{gameHistory.map(game => <Game key={game.gameName} game={game} />)}
</FormSection>
);
}
}
render() {
const {runningGame, showCurrentGame} = this.props;
return (
<FormSection className="user-settings-games" tag={FormTitleTags.H2} title={i18n.Messages.GAME_ACTIVITY}>
<Game game={runningGame} nowPlaying />
<div className="now-playing-add margin-reset margin-top-8 margin-bottom-20">
<span>{i18n.Messages.SETTINGS_GAMES_NOT_SEEING_GAME}</span>
<Popout closeOnScroll={false} render={this.renderPopout} shadow={false} position={Popout.BOTTOM}>
<Button look={ButtonLooks.LINK} size={ButtonSizes.MIN} color={ButtonColors.LINK}>
{i18n.Messages.SETTINGS_GAMES_ADD_GAME}
</Button>
</Popout>
</div>
<SwitchItem className="margin-bottom-40" value={showCurrentGame} onChange={this.handleChangeCurrentGame}>
{i18n.Messages.SHOW_CURRENT_GAME}
</SwitchItem>
{this.renderGameList()}
</FormSection>
);
}
}
export default Flux.connectStores([UserSettingsStore, RunningGameStore], () => {
return {
showCurrentGame: UserSettingsStore.showCurrentGame,
gameHistory: RunningGameStore.getGamesSeen(),
runningGame: RunningGameStore.getRunningGame(),
};
})(UserSettingsGames);
// WEBPACK FOOTER //
// ./discord_app/components/user_settings/UserSettingsGames.js