fix guest mode editor, avoid some illegal actions

pull/114/head
maxime 1 year ago
parent 2577974bfe
commit 32b79ed5c4

@ -1,34 +1,31 @@
import { useRef } from "react"
import { KeyboardEventHandler, RefObject, useRef } from "react"
import Draggable from "react-draggable"
import { BallPiece } from "./BallPiece"
import { NULL_POS } from "../../geo/Pos"
import { NULL_POS, Pos } from "../../geo/Pos"
import { Ball } from "../../model/tactic/CourtObjects"
export interface CourtBallProps {
ball: Ball
}
export interface EditableCourtBallProps extends CourtBallProps {
onPosValidated: (rect: DOMRect) => void
onRemove: () => void
ball: Ball
}
export function CourtBall({ onPosValidated, ball, onRemove }: CourtBallProps) {
const pieceRef = useRef<HTMLDivElement>(null)
const { x, y } = ball.pos
export function CourtBall({ onPosValidated, ball, onRemove }: EditableCourtBallProps) {
const pieceRef = useRef<HTMLDivElement>(null)
return (
<Draggable
onStop={() =>
onPosValidated(pieceRef.current!.getBoundingClientRect())
}
position={NULL_POS}
nodeRef={pieceRef}>
function courtBallPiece({ x, y }: Pos,
pieceRef?: RefObject<HTMLDivElement>,
onKeyUp?: KeyboardEventHandler) {
return (
<div
className={"ball-div"}
ref={pieceRef}
tabIndex={0}
onKeyUp={(e) => {
if (e.key == "Delete") onRemove()
}}
onKeyUp={onKeyUp}
style={{
position: "absolute",
left: `${x * 100}%`,
@ -36,6 +33,30 @@ export function CourtBall({ onPosValidated, ball, onRemove }: CourtBallProps) {
}}>
<BallPiece />
</div>
)
}
if (ball.frozen) {
return courtBallPiece(ball.pos)
}
return (
<Draggable
onStop={() =>
onPosValidated(pieceRef.current!.getBoundingClientRect())
}
position={NULL_POS}
nodeRef={pieceRef}>
{courtBallPiece(
ball.pos,
pieceRef,
(e) => {
if (e.key == "Delete") onRemove()
},
)}
</Draggable>
)
}

@ -258,7 +258,7 @@ export function removePlayer(
content.components,
)!
const actions = playerBefore.actions.filter(
(a) => a.target === pos.attach,
(a) => a.target !== pos.attach,
)
content = updateComponent(
{

@ -77,6 +77,7 @@ export function placeObjectAt(
id: BALL_ID,
pos,
actions: [],
frozen: false
}
break
}
@ -153,6 +154,7 @@ export function placeBallAt(
id: BALL_ID,
pos,
actions: [],
frozen: false,
}
let components = content.components
@ -198,9 +200,9 @@ export function moveComponent(
phantomIdx == 0
? origin
: getComponent(
originPathItems[phantomIdx - 1],
content.components,
)
originPathItems[phantomIdx - 1],
content.components,
)
// detach the action from the screen target and transform it to a regular move action to the phantom.
content = updateComponent(
{
@ -208,18 +210,18 @@ export function moveComponent(
actions: playerBeforePhantom.actions.map((a) =>
a.target === referent
? {
...a,
segments: a.segments.toSpliced(
a.segments.length - 2,
1,
{
...a.segments[a.segments.length - 1],
next: component.id,
},
),
target: component.id,
type: ActionKind.MOVE,
}
...a,
segments: a.segments.toSpliced(
a.segments.length - 2,
1,
{
...a.segments[a.segments.length - 1],
next: component.id,
},
),
target: component.id,
type: ActionKind.MOVE,
}
: a,
),
},
@ -232,9 +234,9 @@ export function moveComponent(
...component,
pos: isPhantom
? {
type: "fixed",
...newPos,
}
type: "fixed",
...newPos,
}
: newPos,
},
content,
@ -313,12 +315,15 @@ export function computeTerminalState(
content.components.filter((c) => c.type !== "phantom") as (
| Player
| CourtObject
)[]
)[]
const componentsTargetedState = nonPhantomComponents.map((comp) =>
comp.type === "player"
? getPlayerTerminalState(comp, content, computedPositions)
: comp,
: {
...comp,
frozen: true,
},
)
return {
@ -396,6 +401,11 @@ export function drainTerminalStateOnChildContent(
): StepContent | null {
let gotUpdated = false
//filter out all frozen components that are not present on the parent's terminal state anymore
childContent = {
components: childContent.components.filter(comp => comp.type === "phantom" || (comp.frozen && tryGetComponent(comp.id, parentTerminalState.components)))
}
for (const parentComponent of parentTerminalState.components) {
const childComponent = tryGetComponent(
parentComponent.id,

@ -7,4 +7,6 @@ export const BALL_TYPE = "ball"
//place here all different kinds of objects
export type CourtObject = Ball
export type Ball = Component<typeof BALL_TYPE, Pos>
export interface Ball extends Component<typeof BALL_TYPE, Pos> {
readonly frozen: boolean
}

@ -131,7 +131,7 @@ function EditorPortal({ guestMode }: EditorPageProps) {
function GuestModeEditor() {
const storageContent = localStorage.getItem(
GUEST_MODE_STEP_CONTENT_STORAGE_KEY + "0",
GUEST_MODE_STEP_CONTENT_STORAGE_KEY + ROOT_STEP_ID,
)
const stepInitialContent: StepContent = {
@ -148,7 +148,7 @@ function GuestModeEditor() {
if (storageContent == null) {
localStorage.setItem(
GUEST_MODE_STEP_ROOT_NODE_INFO_STORAGE_KEY,
JSON.stringify({ id: 0, children: [] }),
JSON.stringify({ id: ROOT_STEP_ID, children: [] }),
)
localStorage.setItem(
GUEST_MODE_STEP_CONTENT_STORAGE_KEY + ROOT_STEP_ID,
@ -156,6 +156,8 @@ function GuestModeEditor() {
)
}
const tacticName = localStorage.getItem(GUEST_MODE_TITLE_STORAGE_KEY) ?? "Nouvelle Tactique"
const courtRef = useRef<HTMLDivElement>(null)
const [stepId, setStepId] = useState(ROOT_STEP_ID)
const [stepContent, setStepContent, saveState] = useContentState(
@ -212,9 +214,7 @@ function GuestModeEditor() {
tactic={{
id: -1,
rootStepNode,
name:
localStorage.getItem(GUEST_MODE_TITLE_STORAGE_KEY) ??
"Nouvelle Tactique",
name: tacticName,
courtType: "PLAIN",
}}
courtRef={courtRef}
@ -244,9 +244,10 @@ function GuestModeEditor() {
const nodeId = getAvailableId(root)
const node = { id: nodeId, children: [] }
const resultTree = addStepNode(root, parent, node)
localStorage.setItem(
GUEST_MODE_STEP_ROOT_NODE_INFO_STORAGE_KEY,
JSON.stringify(addStepNode(root, parent, node)),
JSON.stringify(resultTree),
)
localStorage.setItem(
GUEST_MODE_STEP_CONTENT_STORAGE_KEY + node.id,

Loading…
Cancel
Save