diff --git a/src/components/ChallengeModal/ChallengeModal.tsx b/src/components/ChallengeModal/ChallengeModal.tsx index 077374e934..3ea92fa61e 100644 --- a/src/components/ChallengeModal/ChallengeModal.tsx +++ b/src/components/ChallengeModal/ChallengeModal.tsx @@ -163,6 +163,7 @@ export class ChallengeModal extends Modal super(props); const speed = data.get("challenge.speed", "live"); + //console.log(this.props); const challenge: ChallengeDetails = data.get(`challenge.challenge.${speed}`, { initialized: false, @@ -1834,6 +1835,7 @@ export function challenge( />, ); } + export function createDemoBoard( players_list?: Array<{ name: string; rank: number }>, tournament_record_id?: number, @@ -1852,6 +1854,7 @@ export function createDemoBoard( export function challengeComputer() { return challenge(null, null, true); } + export function challengeRematch( goban: Goban, opponent: GoEnginePlayerEntry, diff --git a/src/components/MiniAutomatch/MiniAutomatch.styl b/src/components/MiniAutomatch/MiniAutomatch.styl new file mode 100644 index 0000000000..c262dac337 --- /dev/null +++ b/src/components/MiniAutomatch/MiniAutomatch.styl @@ -0,0 +1,114 @@ +/* from play.styl */ + +.automatch-container { + flex-grow: 1; + flex-basis: 20rem; + width: 100%; + max-width: 100%; + align-self: center; + + .small-spinner { + width: 20px; + height: 20px; + position: relative; + } + } + +.more-options{ + margin-right: 1rem; + } + +.automatch-header { + flex-shrink: 0; + flex-grow: 0; + flex-basis: 2.5rem; + font-size: 1.3rem; + display: flex; + justify-content: space-between; + align-items: center; + + .btn-group { + display: flex; + flex-wrap: nowrap; + margin-left: 1rem; + } + } + +.automatch-row-container { + flex-grow: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + + .automatch-row { + display: flex; + justify-content: space-around; + align-content: stretch + width: 100%; + flex-wrap: wrap; + + button { + font-size: 1.1rem; + font-weight: bold; + flex-grow: 1; + flex-basis: 13rem; + max-width: 13rem; + height: 4rem; + margin: 0.5rem; + white-space: nowrap; + display: flex; + align-items: center; + align-content: center; + justify-content: center; + + .play-button-text-root { + position: relative; + height: 1.5rem; + + + .time-per-move { + position: absolute; + bottom: -1.2rem; + left: 0; + right: 0; + text-align: center; + } + } + + .fa, .ogs-turtle { + margin: 0.2rem; + } + + .ogs-turtle { + position: relative; + width: 1.0rem; + } + .ogs-turtle::before { + position: absolute; + top: -0.5rem; + left: 0; + } + + .time-per-move { + font-size: font-size-smaller; + } + } + } + + .automatch-settings { + font-size: 1rem; + flex: 0; + text-align: left; + white-space: nowrap; + + .automatch-settings-link { + cursor: pointer; + user-select: none; + } + + i { + padding-right: 0.25rem; + } + } diff --git a/src/components/MiniAutomatch/MiniAutomatch.tsx b/src/components/MiniAutomatch/MiniAutomatch.tsx new file mode 100644 index 0000000000..ec79313365 --- /dev/null +++ b/src/components/MiniAutomatch/MiniAutomatch.tsx @@ -0,0 +1,284 @@ +/* + * Copyright (C) Online-Go.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import * as React from "react"; +import { Link } from "react-router-dom"; + +import { _, pgettext } from "translate"; +import * as data from "data"; + +import { bot_count } from "bots"; +import { challengeComputer } from "ChallengeModal"; +import { automatch_manager, AutomatchPreferences } from "automatch_manager"; +import { getAutomatchSettings } from "AutomatchSettings"; +import { Size } from "src/lib/types"; +import { dup, uuid } from "misc"; +import { alert } from "swal_config"; + +export interface MiniAutomatchState { + automatch_size_options: Size[]; + showLoadingSpinnerForCorrespondence: boolean; +} + +export class MiniAutomatch extends React.Component<{}, MiniAutomatchState> { + constructor(props) { + super(props); + + this.state = { + automatch_size_options: data.get("automatch.size_options", ["9x9", "13x13", "19x19"]), + showLoadingSpinnerForCorrespondence: false, + }; + } + + componentDidMount() { + automatch_manager.on("entry", this.onAutomatchEntry); + automatch_manager.on("start", this.onAutomatchStart); + automatch_manager.on("cancel", this.onAutomatchCancel); + } + + componentWillUnmount() { + automatch_manager.off("entry", this.onAutomatchEntry); + automatch_manager.off("start", this.onAutomatchStart); + automatch_manager.off("cancel", this.onAutomatchCancel); + } + + user = data.get("user"); + anon = this.user.anonymous; + warned = this.user.has_active_warning_flag; + + onAutomatchEntry = () => { + this.forceUpdate(); + }; + + onAutomatchStart = () => { + this.forceUpdate(); + }; + + onAutomatchCancel = () => { + this.forceUpdate(); + }; + + toggleSize(size) { + let size_options = dup(this.state.automatch_size_options); + if (size_options.indexOf(size) >= 0) { + size_options = size_options.filter((x) => x !== size); + } else { + size_options.push(size); + } + if (size_options.length === 0) { + size_options.push("19x19"); + } + data.set("automatch.size_options", size_options); + this.setState({ automatch_size_options: size_options }); + } + + size_enabled = (size) => { + return this.state.automatch_size_options.indexOf(size) >= 0; + }; + + findMatch = (speed: "blitz" | "live" | "correspondence") => { + const settings = getAutomatchSettings(speed); + const preferences: AutomatchPreferences = { + uuid: uuid(), + size_speed_options: this.state.automatch_size_options.map((size) => { + return { + size: size, + speed: speed, + }; + }), + lower_rank_diff: settings.lower_rank_diff, + upper_rank_diff: settings.upper_rank_diff, + rules: { + condition: settings.rules.condition, + value: settings.rules.value, + }, + time_control: { + condition: settings.time_control.condition, + value: settings.time_control.value, + }, + handicap: { + condition: settings.handicap.condition, + value: settings.handicap.value, + }, + }; + preferences.uuid = uuid(); + automatch_manager.findMatch(preferences); + this.onAutomatchEntry(); + + if (speed === "correspondence") { + this.setState({ showLoadingSpinnerForCorrespondence: true }); + } + }; + + dismissCorrespondenceSpinner = () => { + this.setState({ showLoadingSpinnerForCorrespondence: false }); + }; + + cancelActiveAutomatch = () => { + if (automatch_manager.active_live_automatcher) { + automatch_manager.cancel(automatch_manager.active_live_automatcher.uuid); + } + this.forceUpdate(); + }; + + newComputerGame = () => { + if (bot_count() === 0) { + void alert.fire(_("Sorry, all bots seem to be offline, please try again later.")); + return; + } + challengeComputer(); + }; + + render() { + if (automatch_manager.active_live_automatcher) { + return ( +
+

{_("New Game")}

+
{_("Finding you a game...")}
+
+
+
+
+
+
+
+ +
+
+ ); + } else if (this.state.showLoadingSpinnerForCorrespondence) { + return ( +
+

{_("New Game")}

+
{_("Finding you a game...")}
+
+ {_( + 'This can take several minutes. You will be notified when your match has been found. To view or cancel your automatch requests, please Play page section labeled "Your Automatch Requests".', + )} + + {_("Play page")} + +
+
+ +
+
+ ); + } else { + return ( +
+

{_("New Game")}

+
+
+ + + +
+
+ More Options +
+
+
+
+ + + + +
+
+
+ ); + } + } +} diff --git a/src/components/MiniAutomatch/index.ts b/src/components/MiniAutomatch/index.ts new file mode 100644 index 0000000000..88cdb6dab3 --- /dev/null +++ b/src/components/MiniAutomatch/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright (C) Online-Go.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +export * from "./MiniAutomatch"; diff --git a/src/views/Overview/EXV6Overview.tsx b/src/views/Overview/EXV6Overview.tsx index 30a4088425..f787bbbb21 100644 --- a/src/views/Overview/EXV6Overview.tsx +++ b/src/views/Overview/EXV6Overview.tsx @@ -37,6 +37,7 @@ import { ActiveTournamentList, Group } from "src/lib/types"; import { DismissableMessages } from "DismissableMessages"; import { EmailBanner } from "EmailBanner"; import { ActiveDroppedGameList } from "ActiveDroppedGameList"; +import { MiniAutomatch } from "MiniAutomatch"; declare let ogs_missing_translation_count: number; @@ -164,11 +165,14 @@ export class EXV6Overview extends React.Component<{}, OverviewState> { )} {this.state.resolved && ( - + + + + )} diff --git a/src/views/Overview/Overview.styl b/src/views/Overview/Overview.styl index c441d57b14..4842d5cf2d 100644 --- a/src/views/Overview/Overview.styl +++ b/src/views/Overview/Overview.styl @@ -183,6 +183,4 @@ margin-top: 2rem; } } -} - - +} \ No newline at end of file diff --git a/src/views/Overview/Overview.tsx b/src/views/Overview/Overview.tsx index c45b02b3ab..1dcaa64757 100644 --- a/src/views/Overview/Overview.tsx +++ b/src/views/Overview/Overview.tsx @@ -43,6 +43,7 @@ import { EXV6Overview } from "./EXV6Overview"; import { EmailBanner } from "EmailBanner"; import { PaymentProblemBanner } from "PaymentProblemBanner"; import { ActiveDroppedGameList } from "ActiveDroppedGameList"; +import { MiniAutomatch } from "MiniAutomatch"; declare let ogs_missing_translation_count: number; @@ -153,7 +154,7 @@ export class OldOverview extends React.Component<{}, OverviewState> { {_("You're not currently playing any games.")} - {_("Find a game")} + {_("The play page has more game options")} ); @@ -186,11 +187,14 @@ export class OldOverview extends React.Component<{}, OverviewState> { )} {this.state.resolved && ( - + + + + )}