Skip to content

Commit

Permalink
Fork Modal
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Casal authored and Andrew Casal committed Oct 24, 2024
1 parent 27268d0 commit 806870e
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 92 deletions.
123 changes: 49 additions & 74 deletions src/components/ChallengeModal/ForkModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,94 +18,69 @@
import * as React from "react";
import * as data from "@/lib/data";
import { _ } from "@/lib/translate";
import { Modal, openModal } from "@/components/Modal";
import { GobanRenderer } from "goban";
import { PlayerAutocomplete } from "@/components/PlayerAutocomplete";
import { MiniGoban } from "@/components/MiniGoban";
import { challenge } from "@/components/ChallengeModal";
import { PlayerCacheEntry } from "@/lib/player_cache";

interface Events {}
import { ModalContext } from "../Modal/ModalProvider";

interface ForkModalProperties {
goban: GobanRenderer;
}

export class ForkModal extends Modal<Events, ForkModalProperties, any> {
constructor(props: ForkModalProperties) {
super(props);
export const ForkModal = ({ goban }: ForkModalProperties) => {
const [currPlayer, setCurrPlayer] = React.useState(null as PlayerCacheEntry | null);
const { hideModal } = React.useContext(ModalContext);

const goban = this.props.goban;
this.state = {
player: null,
fork_preview: {
//"moves": goban.engine.cur_move.getMoveStringToThisPoint(),
//"initial_state": goban.engine.initial_state,
//"initial_player": goban.engine.config.initial_player,
moves: [],
initial_state: goban.engine.computeInitialStateForForkedGame(),
initial_player: goban.engine.colorToMove(),
width: goban.engine.width,
height: goban.engine.height,
rules: goban.engine.rules,
handicap: goban.engine.handicap,
komi: goban.engine.komi,
move_number: goban.engine.getMoveNumber(),
game_name: goban.engine.name,
},
};
}
const forkPreview = {
moves: [],
initial_state: goban.engine.computeInitialStateForForkedGame(),
initial_player: goban.engine.colorToMove(),
width: goban.engine.width,
height: goban.engine.height,
rules: goban.engine.rules,
handicap: goban.engine.handicap,
komi: goban.engine.komi,
move_number: goban.engine.getMoveNumber(),
game_name: goban.engine.name,
};

openChallengeModal = () => {
this.close();
challenge(this.state.player.id, this.state.fork_preview);
const openChallengeModal = () => {
hideModal();
if (currPlayer) {
challenge(currPlayer.id, forkPreview);
}
};

setPlayer = (player: PlayerCacheEntry | null) => {
this.setState({ player: player });
const setPlayer = (player: PlayerCacheEntry | null) => {
setCurrPlayer(player);
};

render() {
return (
<div className="Modal ForkModal">
<div className="header space-around">
<h2>{_("Player to challenge")}:</h2>{" "}
<PlayerAutocomplete onComplete={this.setPlayer} />
</div>
<div className="body space-around">
<MiniGoban
game_id={0}
black={undefined}
white={undefined}
json={this.state.fork_preview}
noLink
/>
</div>
<div className="buttons">
<button onClick={this.close}>{_("Cancel")}</button>
<button
className="primary"
disabled={
this.state.player == null ||
this.state.player.id === data.get("user").id
}
onClick={this.openChallengeModal}
>
{_("Game settings")} &rarr;
</button>
</div>
return (
<div className="Modal ForkModal">
<div className="header space-around">
<h2>{_("Player to challenge")}:</h2> <PlayerAutocomplete onComplete={setPlayer} />
</div>
);
}
}

export function openForkModal(goban: GobanRenderer) {
return openModal(<ForkModal goban={goban} />);
}
export function challengeFromBoardPosition(goban: GobanRenderer) {
if (!goban) {
return;
}

openForkModal(goban);
}
<div className="body space-around">
<MiniGoban
game_id={0}
black={undefined}
white={undefined}
json={forkPreview}
noLink
/>
</div>
<div className="buttons">
<button onClick={hideModal}>{_("Cancel")}</button>
<button
className="primary"
disabled={currPlayer == null || currPlayer.id === data.get("user").id}
onClick={openChallengeModal}
>
{_("Game settings")} &rarr;
</button>
</div>
</div>
);
};
18 changes: 16 additions & 2 deletions src/components/Modal/ModalProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,18 @@ import * as React from "react";
import { ChallengeModal, ChallengeModes } from "../ChallengeModal";
import { createPortal } from "react-dom";
import { LanguagePickerModal } from "../LanguagePicker";
import { ForkModal } from "../ChallengeModal/ForkModal";
import { GobanRenderer } from "goban";

type ModalProviderType = {
showModal: (type: ModalTypes) => void;
showModal: (type: ModalTypes, props?: ModalTypesProps) => void;
hideModal: () => void;
};

export enum ModalTypes {
Challenge = "challenge",
LanguagePicker = "languagePicker",
Fork = "fork",
}

interface Modals {
Expand All @@ -38,6 +41,9 @@ interface Modals {
playerId?: number;
initialState: any;
};
fork: {
goban: GobanRenderer;
};
}

type ModalTypesProps = {
Expand All @@ -53,7 +59,7 @@ export const ModalProvider = ({ children }: React.PropsWithChildren): JSX.Elemen
const [modalType, setModalType] = React.useState(null as ModalTypes | null);
const [modalProps, setModalProps] = React.useState({} as ModalTypesProps);

const showModal = (type: ModalTypes) => {
const showModal = (type: ModalTypes, props?: ModalTypesProps) => {
setModalType(type);

switch (type) {
Expand All @@ -64,6 +70,11 @@ export const ModalProvider = ({ children }: React.PropsWithChildren): JSX.Elemen
playerId: undefined,
});
break;
case ModalTypes.Fork:
setModalProps({
goban: (props as Modals["fork"]).goban,
});
break;
default:
break;
}
Expand Down Expand Up @@ -99,6 +110,9 @@ export const ModalProvider = ({ children }: React.PropsWithChildren): JSX.Elemen
/>
)}
{modalType === ModalTypes.LanguagePicker && <LanguagePickerModal />}
{modalType === ModalTypes.Fork && (
<ForkModal {...(modalProps as Modals["fork"])} />
)}
</div>,
document.body,
)}
Expand Down
45 changes: 29 additions & 16 deletions src/views/Game/GameDock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import { openGameLinkModal } from "./GameLinkModal";
import { openGameLogModal } from "./GameLogModal";
import { sfx } from "@/lib/sfx";
import { alert } from "@/lib/swal_config";
import { challengeFromBoardPosition } from "@/components/ChallengeModal/ForkModal";
import { errorAlerter } from "@/lib/misc";
import { doAnnul } from "@/lib/moderation";
import { openReport } from "@/components/Report";
Expand All @@ -39,6 +38,7 @@ import { openGameInfoModal } from "./GameInfoModal";
import { useUserIsParticipant } from "./GameHooks";
import { useGoban } from "./goban_context";
import { Tooltip } from "../../components/Tooltip";
import { ModalConsumer, ModalTypes } from "@/components/Modal/ModalProvider";

interface DockProps {
annulled: boolean;
Expand Down Expand Up @@ -139,11 +139,6 @@ export function GameDock({
}
};

const fork = () => {
if (!user.anonymous && !engine.rengo && !goban.isAnalysisDisabled()) {
challengeFromBoardPosition(goban);
}
};
const showLinkModal = () => {
openGameLinkModal(goban);
};
Expand Down Expand Up @@ -446,16 +441,34 @@ export function GameDock({
</a>
</Tooltip>
<Tooltip tooltipRequired={tooltipRequired} title={_("Fork game")}>
<a
onClick={fork}
className={
user.anonymous || engine.rengo || goban.isAnalysisDisabled()
? "disabled"
: ""
}
>
<i className="fa fa-code-fork"></i> {_("Fork game")}
</a>
<ModalConsumer>
{({ showModal }) => (
<a
onClick={() => {
if (
!user.anonymous &&
!engine.rengo &&
!goban.isAnalysisDisabled()
) {
if (!goban) {
return;
}

return showModal(ModalTypes.Fork, {
goban,
});
}
}}
className={
user.anonymous || engine.rengo || goban.isAnalysisDisabled()
? "disabled"
: ""
}
>
<i className="fa fa-code-fork"></i> {_("Fork game")}
</a>
)}
</ModalConsumer>
</Tooltip>
<Tooltip tooltipRequired={tooltipRequired} title={_("Call moderator")}>
<a onClick={alertModerator} className={user.anonymous ? "disabled" : ""}>
Expand Down

0 comments on commit 806870e

Please sign in to comment.