Skip to content

Commit

Permalink
Use BetaMove.target in UI
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasPickering committed Jul 29, 2023
1 parent 4623bb0 commit 6e317d4
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 81 deletions.
3 changes: 3 additions & 0 deletions ui/relay.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ module.exports = {
language: "typescript",
excludes: ["/node_modules/", "/build/"],
noFutureProofEnums: true,
featureFlags: {
enable_relay_resolver_transform: true,
},
};
4 changes: 4 additions & 0 deletions ui/src/components/CoreContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import environment from "util/environment";
import theme, { globalStyles } from "util/theme";
import React, { Suspense } from "react";
import { BrowserRouter } from "react-router-dom";
import relayRuntime from "relay-runtime";
import { RelayEnvironmentProvider } from "react-relay";
import { ThemeProvider } from "@mui/material/styles";
import { CssBaseline, GlobalStyles } from "@mui/material";
Expand All @@ -17,6 +18,9 @@ import LogInPage from "./Account/LogInPage";
import UserQueryProvider from "./UserQueryProvider";
import GuestUserWarningDialog from "./Account/GuestUserWarningDialog";

// https://relay.dev/docs/guides/relay-resolvers/#current-limitations
relayRuntime.RelayFeatureFlags.ENABLE_RELAY_RESOLVERS = true;

// Code splitting!
const HomePage = React.lazy(
() => import(/* webpackChunkName: "Home" */ "components/Home/HomePage")
Expand Down
11 changes: 4 additions & 7 deletions ui/src/components/Editor/EditorControls/BetaMoveListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { isDefined } from "util/func";
import React from "react";
import {
DragHandle as IconDragHandle,
Close as IconClose,
DragHandle as IconDragHandle,
} from "@mui/icons-material";
import {
Box,
Expand All @@ -14,6 +13,7 @@ import {
alpha,
} from "@mui/material";
import { formatBodyPart } from "components/Editor/util/svg";
import React from "react";
import { graphql, useFragment } from "react-relay";
import { BetaMoveIconWrapped } from "../EditorSvg/BetaEditor/BetaMoveIcon";
import { useBetaMoveColor } from "../util/moves";
Expand Down Expand Up @@ -54,14 +54,11 @@ const BetaMoveListItem = React.forwardRef<HTMLLIElement, Props>(
order
annotation
isStart
hold {
id
}
isFree @required(action: THROW)
}
`,
betaMoveKey
);
const isFree = !isDefined(betaMove.hold);

const color = useBetaMoveColor()(betaMove.id);
return (
Expand Down Expand Up @@ -117,7 +114,7 @@ const BetaMoveListItem = React.forwardRef<HTMLLIElement, Props>(
order={betaMove.order}
color={color}
isStart={betaMove.isStart}
isFree={isFree}
isFree={betaMove.isFree}
/>
</ListItemIcon>

Expand Down
26 changes: 12 additions & 14 deletions ui/src/components/Editor/EditorSvg/BetaEditor/BetaMoveMark.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { isDefined } from "util/func";
import { useRef, useState } from "react";
import {
Delete as IconDelete,
Notes as IconNotes,
OpenWith as IconOpenWith,
} from "@mui/icons-material";
import { ClickAwayListener, useTheme } from "@mui/material";
import {
DragFinishHandler,
useDrag,
useDragLayer,
} from "components/Editor/util/dnd";
import { ClickAwayListener, useTheme } from "@mui/material";
import { graphql, useFragment } from "react-relay";
import {
useBetaMoveColor,
useBetaMoveVisualPosition,
} from "components/Editor/util/moves";
import {
OpenWith as IconOpenWith,
Delete as IconDelete,
Notes as IconNotes,
} from "@mui/icons-material";
import { useRef, useState } from "react";
import { graphql, useFragment } from "react-relay";
import ActionOrb from "../common/ActionOrb";
import ActionOrbs from "../common/ActionOrbs";
import Positioned from "../common/Positioned";
import ActionOrb from "../common/ActionOrb";
import SvgTooltip from "../common/SvgTooltip";
import { BetaMoveMark_betaMoveNode$key } from "./__generated__/BetaMoveMark_betaMoveNode.graphql";
import BetaMoveIcon from "./BetaMoveIcon";
import { BetaMoveMark_betaMoveNode$key } from "./__generated__/BetaMoveMark_betaMoveNode.graphql";

interface Props {
betaMoveKey: BetaMoveMark_betaMoveNode$key;
Expand Down Expand Up @@ -49,11 +49,9 @@ const BetaMoveMark: React.FC<Props> = ({
id
bodyPart
order
hold {
id
}
isStart
annotation
isFree @required(action: THROW)
}
`,
betaMoveKey
Expand Down Expand Up @@ -116,7 +114,7 @@ const BetaMoveMark: React.FC<Props> = ({
bodyPart={betaMove.bodyPart}
order={betaMove.order}
isStart={betaMove.isStart}
isFree={!isDefined(betaMove.hold)}
isFree={betaMove.isFree}
// Override color while relocating
color={isRelocating ? palette.editor.actions.relocate.main : color}
icon={isRelocating ? <IconOpenWith /> : undefined}
Expand Down
41 changes: 14 additions & 27 deletions ui/src/components/Editor/util/moves.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import {
moveArrayElement,
} from "util/func";
import { hexToHtml, htmlToHex, lerpColor } from "util/math";
import { disambiguationDistance } from "styles/svg";
import { useContext, useCallback } from "react";
import { graphql } from "relay-runtime";
import { useFragment } from "react-relay";
import { useTheme } from "@mui/material";
import { add, BodyPart, OverlayPosition, polarToSvg } from "./svg";
import { BetaContext } from "./context";
import { moves_visualPositions_betaMoveNodeConnection$key } from "./__generated__/moves_visualPositions_betaMoveNodeConnection.graphql";
import { useCallback, useContext } from "react";
import { useFragment } from "react-relay";
import { graphql } from "relay-runtime";
import { disambiguationDistance } from "styles/svg";
import { moves_colors_betaMoveNodeConnection$key } from "./__generated__/moves_colors_betaMoveNodeConnection.graphql";
import { moves_visualPositions_betaMoveNodeConnection$key } from "./__generated__/moves_visualPositions_betaMoveNodeConnection.graphql";
import { BetaContext } from "./context";
import { BodyPart, OverlayPosition, add, polarToSvg } from "./svg";

/**
* List of beta moves, from Relay, that we will update locally for the purpose
Expand Down Expand Up @@ -110,17 +110,12 @@ export function useBetaMoveVisualPositions(
node {
id
bodyPart
hold {
id
position {
x
y
position @required(action: THROW)
target {
... on HoldNode {
id
}
}
position {
x
y
}
}
}
}
Expand All @@ -133,15 +128,7 @@ export function useBetaMoveVisualPositions(

// Start by just jamming every move into the map
for (const { node } of moves) {
// Grab position from either the hold (for attached moves) or the move
// itself (for free moves)
const position = node.position ?? node.hold?.position;
if (position) {
positionMap.set(node.id, position);
} else {
// eslint-disable-next-line no-console
console.warn("No position available for move:", node);
}
positionMap.set(node.id, node.position);
}

// Next, we'll apply offsets to moves that share the same hold+body part, so
Expand All @@ -156,8 +143,8 @@ export function useBetaMoveVisualPositions(
for (const movesByHold of groupBy(
// Exclude free moves, since they'll never share the *exact* some position
// Maybe we'll need a more dynamic disambiguation, but not yet
moves.filter(({ node }) => isDefined(node.hold)),
({ node }) => node.hold?.id
moves.filter(({ node }) => isDefined(node.target.id)),
({ node }) => node.target.id
).values()) {
const movesByBodyPart = groupBy(movesByHold, ({ node }) => node.bodyPart);

Expand Down
89 changes: 56 additions & 33 deletions ui/src/components/Editor/util/useBetaMoveMutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import { findNode, isDefined } from "util/func";
import useMutation, { MutationState } from "util/useMutation";
import { graphql, useFragment } from "react-relay";
import { generateUniqueClientID } from "relay-runtime";
import { DropResult } from "./dnd";
import { useStanceControls } from "./stance";
import { BodyPart, OverlayPosition } from "./svg";
import { useBetaMoveMutations_createBetaMoveMutation } from "./__generated__/useBetaMoveMutations_createBetaMoveMutation.graphql";
import { useBetaMoveMutations_betaNode$key } from "./__generated__/useBetaMoveMutations_betaNode.graphql";
import { useBetaMoveMutations_createBetaMoveMutation } from "./__generated__/useBetaMoveMutations_createBetaMoveMutation.graphql";
import { useBetaMoveMutations_deleteBetaMoveMutation } from "./__generated__/useBetaMoveMutations_deleteBetaMoveMutation.graphql";
import { useBetaMoveMutations_updateBetaMoveAnnotationMutation } from "./__generated__/useBetaMoveMutations_updateBetaMoveAnnotationMutation.graphql";
import { useBetaMoveMutations_relocateBetaMoveMutation } from "./__generated__/useBetaMoveMutations_relocateBetaMoveMutation.graphql";
import { useBetaMoveMutations_updateBetaMoveAnnotationMutation } from "./__generated__/useBetaMoveMutations_updateBetaMoveAnnotationMutation.graphql";
import { DropResult } from "./dnd";
import { createBetaMoveLocal, deleteBetaMoveLocal } from "./moves";
import { useStanceControls } from "./stance";
import { BodyPart, OverlayPosition } from "./svg";

interface Mutation<T> {
callback: (data: T) => void;
Expand Down Expand Up @@ -117,17 +117,20 @@ function useBetaMoveMutations(betaKey: useBetaMoveMutations_betaNode$key): {
# These are the only fields we modify
# Yes, we need to refetch both positions, in case the move was
# converted from free to attached or vice versa
hold {
id
position {
target {
__typename
... on HoldNode {
id
position {
x
y
}
}
... on SVGPosition {
x
y
}
}
position {
x
y
}
}
}
`);
Expand Down Expand Up @@ -181,10 +184,7 @@ function useBetaMoveMutations(betaKey: useBetaMoveMutations_betaNode$key): {
bodyPart,
annotation: "",
isStart: false, // Punting on calculating this for now
hold:
dropResult.kind === "hold" ? { id: dropResult.holdId } : null,
position:
dropResult.kind === "dropZone" ? dropResult.position : null,
target: getOptimisticTarget(dropResult),
beta: {
id: beta.id,
moves: createBetaMoveLocal(beta.moves, optimisticId, newOrder),
Expand Down Expand Up @@ -217,7 +217,7 @@ function useBetaMoveMutations(betaKey: useBetaMoveMutations_betaNode$key): {
optimisticResponse: {
updateBetaMove: {
id: betaMoveId,
...getDropResponse(dropResult),
target: getOptimisticTarget(dropResult),
},
},
});
Expand Down Expand Up @@ -258,12 +258,19 @@ graphql`
order
annotation
isStart
hold {
id
}
position {
x
y
target {
__typename
... on HoldNode {
id
position {
x
y
}
}
... on SVGPosition {
x
y
}
}
}
`;
Expand All @@ -286,24 +293,40 @@ function getDropParams(
}

/**
* Get a set of common response fields for a move mutation, related to the
* object it was dropped onto. These can be used for an optimistic response.
* Get an optimistic value for the `target` field, basd on the object it was
* dropped onto.
* @param dropResult Object that the move was dropped onto to trigger the mutation (hold or free?)
* @returns Params to be passed to a move mutation
* @returns Valid value for the `target` field
*/
function getDropResponse(
function getOptimisticTarget(
dropResult: DropResult<"overlayBetaMove">
):
| { hold: { id: string; position: OverlayPosition }; position: null }
| { hold: null; position: OverlayPosition } {
): // These response types have some weird cruft because of the types that Relay generates :(
| {
__typename: "HoldNode";
__isNode: "HoldNode";
id: string;
position: OverlayPosition;
}
| ({
__typename: "SVGPosition";
__isNode: "SVGPosition";
id: string;
} & OverlayPosition) {
switch (dropResult.kind) {
case "hold":
return {
hold: { id: dropResult.holdId, position: dropResult.position },
position: null,
__typename: "HoldNode",
__isNode: "HoldNode",
id: dropResult.holdId,
position: dropResult.position,
};
case "dropZone":
return { hold: null, position: dropResult.position };
return {
__typename: "SVGPosition",
__isNode: "SVGPosition",
id: "",
...dropResult.position,
};
}
}

Expand Down
34 changes: 34 additions & 0 deletions ui/src/util/resolvers/BetaMoveIsFree.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { graphql } from "relay-runtime";
import { readFragment } from "relay-runtime/lib/store/ResolverFragments";
import { BetaMoveIsFreeResolver$key } from "./__generated__/BetaMoveIsFreeResolver.graphql";

/**
* @RelayResolver
*
* @onType BetaMoveNode
* @fieldName isFree
* @rootFragment BetaMoveIsFreeResolver
*
* Client-side resolver for BetaMove.isFree
* https://relay.dev/docs/guides/relay-resolvers/
*/
export default function betaMoveIsFreeResolver(
betaMoveKey: BetaMoveIsFreeResolver$key
): boolean {
const betaMove = readFragment(
graphql`
fragment BetaMoveIsFreeResolver on BetaMoveNode {
target {
__typename
# Needed to get relay to type __typename
... on HoldNode {
id
}
}
}
`,
betaMoveKey
);

return betaMove.target.__typename !== "HoldNode";
}
Loading

0 comments on commit 6e317d4

Please sign in to comment.