Skip to content

Commit

Permalink
Disable Play and custom buttons when any active game searching mechan…
Browse files Browse the repository at this point in the history
…ism is active
  • Loading branch information
anoek committed Dec 11, 2024
1 parent 755e2d7 commit c4ebec6
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 20 deletions.
13 changes: 7 additions & 6 deletions src/views/Play/CustomGames.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { RengoManagementPane } from "@/components/RengoManagementPane";
import { RengoTeamManagementPane } from "@/components/RengoTeamManagementPane";
import { PlayContext } from "./PlayContext";
import { challenge } from "@/components/ChallengeModal";
import { active_challenges_emitter, useHaveActiveGameSearch } from "./hooks";

const CHALLENGE_LIST_FREEZE_PERIOD = 1000; // Freeze challenge list for this period while they move their mouse on it

Expand All @@ -75,6 +76,8 @@ export function CustomGames(): JSX.Element {
const canvas: HTMLCanvasElement = React.useMemo(() => allocateCanvasOrError(), []);
const seekgraph = React.useRef<SeekGraph>();

const disable_challenge_buttons = useHaveActiveGameSearch();

const [seekGraphVisible, setSeekGraphVisible] = usePreference("show-seek-graph");

const toggleSeekGraph = () => {
Expand Down Expand Up @@ -363,6 +366,9 @@ export function CustomGames(): JSX.Element {
filter: default_filter as ChallengeFilter,
});
seekgraph.current.on("challenges", updateChallenges);
seekgraph.current.on("challenges", (args) => {
active_challenges_emitter.emit("challenges", args);
});

const [match, id] = window.location.hash.match(/#rengo:(\d+)/) || [];
if (match) {
Expand All @@ -371,6 +377,7 @@ export function CustomGames(): JSX.Element {

return () => {
seekgraph.current?.destroy();
active_challenges_emitter.emit("clear");
if (list_freeze_timeout.current) {
clearTimeout(list_freeze_timeout.current);
list_freeze_timeout.current = undefined;
Expand Down Expand Up @@ -398,12 +405,6 @@ export function CustomGames(): JSX.Element {
});
}, [live_list, cancelOpenChallenge]);

const disable_challenge_buttons = !!(
liveOwnChallengePending() ||
live_rengo_challenge_to_show ||
automatch_manager.active_live_automatcher
);

if (!show_custom_games) {
return (
<div>
Expand Down
32 changes: 18 additions & 14 deletions src/views/Play/QuickMatch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import { Link } from "react-router-dom";
import Select, { components } from "react-select";
import { SPEED_OPTIONS } from "./SPEED_OPTIONS";
import { PlayerIcon } from "@/components/PlayerIcon";
import { useHaveActiveGameSearch } from "./hooks";

moment.relativeTimeThreshold("m", 56);
export interface SelectOption {
Expand Down Expand Up @@ -225,6 +226,7 @@ export function QuickMatch(): JSX.Element {
const [bot_spinner, setBotSpinner] = React.useState(false);
const cancel_bot_game = React.useRef<() => void>(() => {});
const [game_clock, setGameClock] = preferences.usePreference("automatch.game-clock");
const have_active_game_search = useHaveActiveGameSearch();

const [multiple_sizes, setMultipleSizes] = preferences.usePreference(
"automatch.multiple-sizes",
Expand Down Expand Up @@ -568,7 +570,7 @@ export function QuickMatch(): JSX.Element {
}, []);
*/

const search_active =
const automatch_search_active =
!!automatch_manager.active_live_automatcher || correspondence_spinner || bot_spinner;

function isSizeActive(size: Size) {
Expand Down Expand Up @@ -832,7 +834,7 @@ export function QuickMatch(): JSX.Element {
getActivityClass(s)
}
key={s}
disabled={search_active}
disabled={automatch_search_active}
onClick={() => {
toggleSize(s);
}}
Expand Down Expand Up @@ -933,7 +935,7 @@ export function QuickMatch(): JSX.Element {
getActivityClass(board_size, speed, "fischer")
}
disabled={
search_active ||
automatch_search_active ||
(game_clock === "multiple" &&
speed === "correspondence")
}
Expand Down Expand Up @@ -982,7 +984,7 @@ export function QuickMatch(): JSX.Element {
onClick={() => {
toggleSpeedSystem(speed, "byoyomi");
}}
disabled={search_active}
disabled={automatch_search_active}
>
{selected_size_count > 1 &&
speed !== "correspondence"
Expand Down Expand Up @@ -1023,10 +1025,10 @@ export function QuickMatch(): JSX.Element {
className={
"opponent-option-container " +
(opponent === "human" ? "active" : "") +
(search_active ? " disabled" : "")
(automatch_search_active ? " disabled" : "")
}
onClick={() => {
if (search_active) {
if (automatch_search_active) {
return;
}
setOpponent("human");
Expand All @@ -1039,7 +1041,7 @@ export function QuickMatch(): JSX.Element {
<select
value={lower_rank_diff}
onChange={(ev) => setLowerRankDiff(parseInt(ev.target.value))}
disabled={search_active}
disabled={automatch_search_active}
>
{user.anonymous ? (
<option>{"30k"}</option>
Expand All @@ -1055,7 +1057,7 @@ export function QuickMatch(): JSX.Element {
<select
value={upper_rank_diff}
onChange={(ev) => setUpperRankDiff(parseInt(ev.target.value))}
disabled={search_active}
disabled={automatch_search_active}
>
{user.anonymous ? (
<option>{"9d"}</option>
Expand All @@ -1074,10 +1076,12 @@ export function QuickMatch(): JSX.Element {
className={
"opponent-option-container " +
(opponent === "bot" ? "active" : "") +
(search_active || game_clock === "multiple" ? " disabled" : "")
(automatch_search_active || game_clock === "multiple"
? " disabled"
: "")
}
onClick={() => {
if (search_active || game_clock === "multiple") {
if (automatch_search_active || game_clock === "multiple") {
return;
}
setOpponent("bot");
Expand Down Expand Up @@ -1106,7 +1110,7 @@ export function QuickMatch(): JSX.Element {
minMenuHeight={400}
maxMenuHeight={400}
menuPlacement="auto"
isDisabled={search_active}
isDisabled={automatch_search_active}
onChange={(opt) => {
if (opt) {
setSelectedBot(opt.id);
Expand Down Expand Up @@ -1142,7 +1146,7 @@ export function QuickMatch(): JSX.Element {
minMenuHeight={400}
maxMenuHeight={400}
menuPlacement="auto"
isDisabled={search_active}
isDisabled={automatch_search_active}
onChange={(opt) => {
if (opt) {
setHandicaps(opt.value as "enabled" | "standard" | "disabled");
Expand Down Expand Up @@ -1225,11 +1229,11 @@ export function QuickMatch(): JSX.Element {
</div>
)}

{!search_active && !user.anonymous && (
{!automatch_search_active && !user.anonymous && (
<button
className="primary play-button"
onClick={play}
disabled={anon || warned}
disabled={anon || warned || have_active_game_search}
>
{_("Play")}
</button>
Expand Down
81 changes: 81 additions & 0 deletions src/views/Play/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/

import * as React from "react";
import { automatch_manager } from "@/lib/automatch_manager";
import { Challenge } from "@/lib/challenge_utils";
import { EventEmitter } from "eventemitter3";

interface Events {
challenges: (challenges: { [id: string]: Challenge } | undefined) => void;
clear: () => void;
}

/* This emitter is called by the CustomGames component which creates the
* SeekGraph instance which does the work of subscribing to this data. */
export const active_challenges_emitter = new EventEmitter<Events>();

export function useHaveActiveGameSearch(): boolean {
const [have_active_automatch, setHaveActiveAutomatch] = React.useState(
automatch_manager.active_live_automatcher,
);
const [have_live_user_challenge, setHaveLiveUserChallenge] = React.useState(false);

React.useEffect(() => {
function updateLiveAutomatcherStatus() {
setHaveActiveAutomatch(automatch_manager.active_live_automatcher);
}

automatch_manager.on("entry", updateLiveAutomatcherStatus);
automatch_manager.on("start", updateLiveAutomatcherStatus);
automatch_manager.on("cancel", updateLiveAutomatcherStatus);

return () => {
automatch_manager.removeListener("entry", updateLiveAutomatcherStatus);
automatch_manager.removeListener("start", updateLiveAutomatcherStatus);
automatch_manager.removeListener("cancel", updateLiveAutomatcherStatus);
};
}, []);

React.useEffect(() => {
function updateChallenges(args?: { [id: string]: Challenge }) {
let found_live_user_challenge = false;

for (const challenge of Object.values(args || {})) {
if (
challenge.user_challenge &&
challenge.time_per_move > 0 &&
challenge.time_per_move < 3600
) {
found_live_user_challenge = true;
}
}

setHaveLiveUserChallenge(found_live_user_challenge);
}

active_challenges_emitter.on("challenges", updateChallenges);
active_challenges_emitter.on("clear", updateChallenges);

return () => {
active_challenges_emitter.removeListener("challenges", updateChallenges);
active_challenges_emitter.removeListener("clear", updateChallenges);
};
}, []);

return !!(have_active_automatch || have_live_user_challenge);
}
1 change: 1 addition & 0 deletions src/views/Play/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
export * from "./Play";
export * from "./ChallengeLists";
export * from "./AvailableQuickMatches";
export * from "./hooks";

0 comments on commit c4ebec6

Please sign in to comment.