Add support for blank characters
This commit is contained in:
parent
c61b2e3f75
commit
cd8a4b73a9
2 changed files with 91 additions and 16 deletions
|
@ -1,6 +1,6 @@
|
|||
import * as React from "react";
|
||||
import {GameWasm, Letter as LetterData, MyResult, PlayedTile, PlayerAndScore, Tray, WordResult} from "word_grid";
|
||||
import {JSX, useEffect, useMemo, useReducer, useState} from "react";
|
||||
import {ChangeEvent, JSX, useEffect, useMemo, useReducer, useState} from "react";
|
||||
|
||||
export enum LocationType {
|
||||
GRID,
|
||||
|
@ -75,8 +75,9 @@ function matchCoordinate(playerLetters: PlayableLetterData[], coords: Coordinate
|
|||
enum TileDispatchActionType {
|
||||
MOVE,
|
||||
RETRIEVE,
|
||||
SET_BLANK,
|
||||
}
|
||||
type TileDispatchAction = {action: TileDispatchActionType, start?: CoordinateData, end?: CoordinateData};
|
||||
type TileDispatchAction = {action: TileDispatchActionType, start?: CoordinateData, end?: CoordinateData, newBlankValue?: string, blankIndex?: number};
|
||||
type TileDispatch = React.Dispatch<TileDispatchAction>;
|
||||
|
||||
function addLogInfo(existingLog: React.JSX.Element[], newItem: React.JSX.Element) {
|
||||
|
@ -124,6 +125,15 @@ export function Game(props: {wasm: GameWasm}) {
|
|||
|
||||
setConfirmedScorePoints(-1);
|
||||
|
||||
return playerLetters.slice();
|
||||
} if (update.action === TileDispatchActionType.SET_BLANK) {
|
||||
const blankLetter = playerLetters[update.blankIndex];
|
||||
if(blankLetter.text !== update.newBlankValue) {
|
||||
blankLetter.text = update.newBlankValue;
|
||||
if (blankLetter.location == LocationType.GRID) {
|
||||
setConfirmedScorePoints(-1);
|
||||
}
|
||||
}
|
||||
return playerLetters.slice();
|
||||
} else {
|
||||
console.error("Unknown tray update");
|
||||
|
@ -221,7 +231,7 @@ export function Game(props: {wasm: GameWasm}) {
|
|||
|
||||
|
||||
|
||||
export function TileSlot(props: { tile: React.JSX.Element | undefined, location: CoordinateData, dispatch: TileDispatch }): React.JSX.Element {
|
||||
export function TileSlot(props: { tile?: React.JSX.Element | undefined, location: CoordinateData, dispatch: TileDispatch }): React.JSX.Element {
|
||||
let isDraggable = props.tile !== undefined;
|
||||
|
||||
function onDragStart(e: React.DragEvent<HTMLDivElement>) {
|
||||
|
@ -252,11 +262,51 @@ export function TileSlot(props: { tile: React.JSX.Element | undefined, location:
|
|||
|
||||
}
|
||||
|
||||
export function Letter(props: { data: LetterData }): React.JSX.Element {
|
||||
return <div className="letter">
|
||||
<div className="text">{props.data.text}</div>
|
||||
<div className="letter-points">{props.data.points}</div>
|
||||
</div>
|
||||
export function Letter(props: { data: LetterData, letterUpdater?: (value: string) => void }): React.JSX.Element {
|
||||
|
||||
function modifyThisLetter(value:string){
|
||||
props.letterUpdater(value);
|
||||
}
|
||||
|
||||
|
||||
function onBlankInput(e: ChangeEvent<HTMLInputElement>){
|
||||
let value = e.target.value.toUpperCase();
|
||||
if(value.length > 1){
|
||||
value = value[value.length - 1];
|
||||
} else if(value.length == 0){
|
||||
modifyThisLetter(value);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now check that it's a letter
|
||||
let is_letter = value.match("[A-Z]") != null;
|
||||
if(is_letter){
|
||||
modifyThisLetter(value);
|
||||
} else {
|
||||
// Cancel and do nothing
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(props.data.is_blank && props.data.ephemeral) {
|
||||
return <div className="letter">
|
||||
<input className="blank-input" type="text" onChange={onBlankInput} value={props.data.text} />
|
||||
<div className="letter-points">{props.data.points}</div>
|
||||
</div>
|
||||
} else {
|
||||
let className = "text";
|
||||
if (props.data.is_blank) { // not ephemeral
|
||||
className += " prev-blank";
|
||||
}
|
||||
return <div className="letter">
|
||||
<div className={className}>{props.data.text}</div>
|
||||
<div className="letter-points">{props.data.points}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -266,24 +316,28 @@ export function TileTray(props: { letters: Array<PlayableLetterData>, trayLength
|
|||
for (let i=0; i<props.trayLength; i++) {
|
||||
elements.push(
|
||||
<TileSlot
|
||||
tile={undefined}
|
||||
key={"empty" + i}
|
||||
location={{location: LocationType.TRAY, index: i}}
|
||||
dispatch={props.dispatch} />
|
||||
);
|
||||
}
|
||||
|
||||
for (let letter of props.letters) {
|
||||
props.letters.forEach((letter, i) => {
|
||||
if (letter.location === LocationType.TRAY) {
|
||||
elements[letter.index] =
|
||||
<TileSlot
|
||||
tile={<Letter data={letter} />}
|
||||
tile={<Letter
|
||||
data={letter}
|
||||
letterUpdater={(value) => {
|
||||
props.dispatch({action: TileDispatchActionType.SET_BLANK, blankIndex: i, newBlankValue: value})
|
||||
}}
|
||||
/>}
|
||||
key={"letter" + letter.index}
|
||||
location={{location: LocationType.TRAY, index: letter.index}}
|
||||
dispatch={props.dispatch} />
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="tray">
|
||||
|
@ -309,7 +363,6 @@ function Grid(props: {
|
|||
tileElement = <>
|
||||
<span>{text}</span>
|
||||
<TileSlot
|
||||
tile={undefined}
|
||||
location={{location: LocationType.GRID, index: i}}
|
||||
dispatch={props.dispatch} /></>;
|
||||
}
|
||||
|
@ -320,7 +373,7 @@ function Grid(props: {
|
|||
</div>;
|
||||
});
|
||||
|
||||
for (let letter of props.playerLetters) {
|
||||
props.playerLetters.forEach((letter, i) => {
|
||||
if (letter.location === LocationType.GRID) {
|
||||
const ct = props.cellTypes[letter.index];
|
||||
const {className, text} = cell_type_to_details(ct);
|
||||
|
@ -328,14 +381,19 @@ function Grid(props: {
|
|||
elements[letter.index] =
|
||||
<div key={"letter" + letter.index} className={"grid-spot " + className}>
|
||||
<TileSlot
|
||||
tile={<Letter data={letter} />}
|
||||
tile={<Letter
|
||||
data={letter}
|
||||
letterUpdater={(value) => {
|
||||
props.dispatch({action: TileDispatchActionType.SET_BLANK, blankIndex: i, newBlankValue: value});
|
||||
}}
|
||||
/>}
|
||||
location={{location: LocationType.GRID, index: letter.index}}
|
||||
dispatch={props.dispatch} />
|
||||
</div>;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return <div className="board-grid">
|
||||
{elements}
|
||||
|
|
|
@ -105,6 +105,23 @@
|
|||
padding-right: 5px;
|
||||
}
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 5px;
|
||||
text-align: center;
|
||||
font-size: @tile-font-size;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-style: italic;
|
||||
left: 0; /* Fixes a weird display bug where the input is shifted to the right when the tile is on the grid */
|
||||
}
|
||||
|
||||
.prev-blank {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.board-log {
|
||||
|
|
Loading…
Reference in a new issue