Refactors detective board (#92054)

## About The Pull Request
Doing some spot touch ups to the detective notice board UI. It had some
improper types, among other crimes. It should totally get a real
refactor by a brave soul.
## Why It's Good For The Game
Code quality
## Changelog
This commit is contained in:
Jeremiah
2025-07-15 21:30:18 +03:00
committed by GitHub
parent abd5296f0b
commit d9e370ef48
8 changed files with 71 additions and 79 deletions
@@ -2,15 +2,16 @@ import { Box, Button } from 'tgui-core/components';
import { classes } from 'tgui-core/react';
import { useBackend } from '../../backend';
import type { DataCase } from './DataTypes';
import type { DataCase } from './types';
type BoardTabsData = {
type Data = {
cases: DataCase[];
current_case: number;
};
const BoardTab = (props) => {
const { color, selected, onClick = () => {}, children } = props;
function BoardTab(props) {
const { color, selected, onClick, children } = props;
return (
<Box
onClick={onClick}
@@ -23,11 +24,12 @@ const BoardTab = (props) => {
<Box className={'BoardTab__Contain'}>{children}</Box>
</Box>
);
};
}
export const BoardTabs = (props) => {
const { act, data } = useBackend<BoardTabsData>();
export function BoardTabs(props) {
const { act, data } = useBackend<Data>();
const { cases, current_case } = data;
return (
<Box className="BoardTabs">
{cases?.map((item, index) => (
@@ -61,4 +63,4 @@ export const BoardTabs = (props) => {
<Button color="transparent" icon="plus" onClick={() => act('add_case')} />
</Box>
);
};
}
@@ -1,46 +1,42 @@
import { useEffect, useMemo, useState } from 'react';
import { Box, Button, Flex, Stack } from 'tgui-core/components';
import type { DataEvidence } from './DataTypes';
import { useBackend } from '../../backend';
import type { Coordinates } from '../common/Connections';
import { Pin } from './Pin';
import type { DataEvidence, EvidenceFn } from './types';
type EvidenceProps = {
type Props = {
case_ref: string;
evidence: DataEvidence;
act: Function;
onPinStartConnecting: Function;
onPinConnected: Function;
onPinMouseUp: Function;
onEvidenceRemoved: Function;
onStartMoving: Function;
onStopMoving: Function;
onMoving: Function;
onEvidenceRemoved: EvidenceFn;
onMoving: (evidence: DataEvidence, position: Coordinates) => void;
onPinConnected: EvidenceFn;
onPinMouseUp: (evidence: DataEvidence, event: any) => void;
onPinStartConnecting: (evidence: DataEvidence, mousePos: Coordinates) => void;
onStartMoving: EvidenceFn;
onStopMoving: EvidenceFn;
};
type Position = {
x: number;
y: number;
};
export function Evidence(props: EvidenceProps) {
const { evidence, case_ref, act } = props;
export function Evidence(props: Props) {
const { act } = useBackend();
const { evidence, case_ref } = props;
const [dragging, setDragging] = useState(false);
const [canDrag, setCanDrag] = useState(true);
const [dragPosition, setDragPosition] = useState<Position>({
const [dragPosition, setDragPosition] = useState<Coordinates>({
x: evidence.x,
y: evidence.y,
});
const [lastMousePosition, setLastMousePosition] = useState<Position | null>(
null,
);
const [lastMousePosition, setLastMousePosition] =
useState<Coordinates | null>(null);
const randomRotation = useMemo(() => Math.random() * 2 - 1, []);
function handleMouseDown(args) {
function handleMouseDown(args: React.MouseEvent<HTMLDivElement>) {
if (canDrag) {
setDragging(true);
props.onStartMoving(evidence);
@@ -128,7 +124,7 @@ export function Evidence(props: EvidenceProps) {
evidence={evidence}
onStartConnecting={(
evidence: DataEvidence,
mousePos: Position,
mousePos: Coordinates,
) => {
setCanDrag(false);
props.onPinStartConnecting(evidence, mousePos);
@@ -137,7 +133,7 @@ export function Evidence(props: EvidenceProps) {
setCanDrag(true);
props.onPinConnected(evidence);
}}
onMouseUp={(evidence: DataEvidence, args) => {
onPinMouseUp={(evidence: DataEvidence, args) => {
setCanDrag(true);
props.onPinMouseUp(evidence, args);
}}
@@ -2,22 +2,23 @@ import { useEffect, useState } from 'react';
import { Box, Stack } from 'tgui-core/components';
import { classes } from 'tgui-core/react';
import type { DataEvidence } from './DataTypes';
import type { Coordinates } from '../common/Connections';
import type { DataEvidence } from './types';
type PinProps = {
type Props = {
evidence: DataEvidence;
onStartConnecting: Function;
onConnected: Function;
onMouseUp: Function;
onStartConnecting: (evidence: DataEvidence, mousePos: Coordinates) => void;
onConnected: (evidence: DataEvidence) => void;
onPinMouseUp: (evidence: DataEvidence, args: any) => void;
};
export function Pin(props: PinProps) {
const { evidence, onStartConnecting, onConnected, onMouseUp } = props;
export function Pin(props: Props) {
const { evidence } = props;
const [creatingRope, setCreatingRope] = useState(false);
function handleMouseDown(args) {
setCreatingRope(true);
onStartConnecting(evidence, {
props.onStartConnecting(evidence, {
x: args.clientX,
y: args.clientY,
});
@@ -27,16 +28,10 @@ export function Pin(props: PinProps) {
if (!creatingRope) {
return;
}
const handleMouseUp = (args: MouseEvent) => {
const handleMouseUp = () => {
if (creatingRope) {
setCreatingRope(false);
onConnected(evidence, {
evidence_ref: 'not used',
position: {
x: args.clientX,
y: args.clientY,
},
});
props.onConnected(evidence);
}
};
window.addEventListener('mouseup', handleMouseUp);
@@ -55,7 +50,7 @@ export function Pin(props: PinProps) {
])}
textAlign="center"
onMouseDown={handleMouseDown}
onMouseUp={(args) => onMouseUp(evidence, args)}
onMouseUp={(args) => props.onPinMouseUp(evidence, args)}
/>
</Stack.Item>
</Stack>
@@ -6,11 +6,11 @@ import { Window } from '../../layouts';
import {
type Connection,
Connections,
type Position,
type Coordinates,
} from '../common/Connections';
import { BoardTabs } from './BoardTabs';
import type { DataCase, DataEvidence } from './DataTypes';
import { Evidence } from './Evidence';
import type { DataCase, DataEvidence } from './types';
type Data = {
cases: DataCase[];
@@ -26,6 +26,14 @@ const PIN_Y_OFFSET = 15;
const PIN_CONNECTING_Y_OFFSET = -60;
function getPinPositionByPosition(evidence: Coordinates): Coordinates {
return { x: evidence.x + 15, y: evidence.y + PIN_Y_OFFSET };
}
function getPinPosition(evidence: DataEvidence): Coordinates {
return getPinPositionByPosition({ x: evidence.x, y: evidence.y });
}
export function DetectiveBoard(props) {
const { act, data } = useBackend<Data>();
@@ -46,7 +54,7 @@ export function DetectiveBoard(props) {
function handlePinStartConnecting(
evidence: DataEvidence,
mousePos: Position,
mousePos: Coordinates,
) {
setConnectingEvidence(evidence);
setConnection({
@@ -56,14 +64,6 @@ export function DetectiveBoard(props) {
});
}
function getPinPositionByPosition(evidence: Position) {
return { x: evidence.x + 15, y: evidence.y + PIN_Y_OFFSET };
}
function getPinPosition(evidence: DataEvidence) {
return getPinPositionByPosition({ x: evidence.x, y: evidence.y });
}
function handlePinConnected(evidence: DataEvidence) {
setConnection(null);
setConnectingEvidence(null);
@@ -219,7 +219,7 @@ export function DetectiveBoard(props) {
setConnections(new_connections);
}
function handleEvidenceMoving(evidence: DataEvidence, position: Position) {
function handleEvidenceMoving(evidence: DataEvidence, position: Coordinates) {
if (movingEvidenceConnections) {
const new_connections: TypedConnection[] = [];
for (const con of movingEvidenceConnections) {
@@ -315,13 +315,12 @@ export function DetectiveBoard(props) {
key={evidence.ref}
evidence={evidence}
case_ref={item.ref}
act={act}
onPinStartConnecting={handlePinStartConnecting}
onEvidenceRemoved={handleEvidenceRemoved}
onMoving={handleEvidenceMoving}
onPinConnected={handlePinConnected}
onPinMouseUp={handleMouseUpOnPin}
onEvidenceRemoved={handleEvidenceRemoved}
onPinStartConnecting={handlePinStartConnecting}
onStartMoving={handleEvidenceStartMoving}
onMoving={handleEvidenceMoving}
onStopMoving={handleEvidenceStopMoving}
/>
))}
@@ -343,11 +342,9 @@ export function DetectiveBoard(props) {
</Box>
</Stack.Item>
<Stack.Item align="center" grow={3}>
<Button
icon="plus"
content="Create case"
onClick={() => act('add_case')}
/>
<Button icon="plus" onClick={() => act('add_case')}>
Create case
</Button>
</Stack.Item>
</Stack>
</Stack.Item>
@@ -19,3 +19,5 @@ export type DataEvidence = {
text: string;
connections: string[];
};
export type EvidenceFn = (evidence: DataEvidence) => void;
@@ -13,7 +13,7 @@ import { Window } from '../../layouts';
import {
type Connection,
Connections,
type Position,
type Coordinates,
} from './../common/Connections';
import { ABSOLUTE_Y_OFFSET } from './../IntegratedCircuit/constants';
import { PlaneEditor } from './PlaneEditor';
@@ -34,7 +34,7 @@ import type {
} from './types';
import { PlaneDebugContext } from './usePlaneDebug';
function getPosition(el: HTMLElement | null): Position {
function getPosition(el: HTMLElement | null): Coordinates {
let xPos = 0;
let yPos = 0;
@@ -1,6 +1,6 @@
import type { BooleanLike } from 'tgui-core/react';
import type { Position } from '../common/Connections';
import type { Coordinates } from '../common/Connections';
export type PlaneDebugData = {
mob_name: string;
@@ -63,7 +63,7 @@ export type Plane = {
incoming_filters: Filter[];
outgoing_relays: Relay[];
outgoing_filters: Filter[];
position: Position;
position: Coordinates;
parents: Plane[];
depth: number;
};
@@ -120,8 +120,8 @@ export type PlaneConnectorElement = {
export type PlaneConnection = {
// Both of these are relay/filter ref -> coordinates for that input/output
input: Position;
output: Position;
input: Coordinates;
output: Coordinates;
};
export type PlaneHighlight = {
@@ -10,16 +10,16 @@ export enum ConnectionStyle {
SUBWAY_SHARP = 'subway sharp',
}
export type Position = {
export type Coordinates = {
x: number;
y: number;
};
export type Connection = {
// X, Y starting point
from: Position;
from: Coordinates;
// X, Y ending point
to: Position;
to: Coordinates;
// Color of the line, defaults to blue
color?: string;
// Type of line - Curvy or Straight / angled, defaults to curvy