From e20ec6686be45329eebccd7772b5950a9a13e6d1 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Mon, 24 Sep 2018 14:12:52 -0700 Subject: [PATCH] Add types for WindowManager --- .../{WindowManager.js => WindowManager.tsx} | 62 ++++++++++++------- js/snapUtils.ts | 8 +-- 2 files changed, 44 insertions(+), 26 deletions(-) rename js/components/{WindowManager.js => WindowManager.tsx} (70%) diff --git a/js/components/WindowManager.js b/js/components/WindowManager.tsx similarity index 70% rename from js/components/WindowManager.js rename to js/components/WindowManager.tsx index 4a9fbba7..5c6a8951 100644 --- a/js/components/WindowManager.js +++ b/js/components/WindowManager.tsx @@ -1,7 +1,7 @@ -import React from "react"; -import PropTypes from "prop-types"; +import React, { ReactNode } from "react"; import { connect } from "react-redux"; +import { Box, Diff } from "../snapUtils"; import * as SnapUtils from "../snapUtils"; import * as Selectors from "../selectors"; import { @@ -9,14 +9,31 @@ import { windowsHaveBeenCentered, centerWindowsIfNeeded } from "../actionCreators"; -const abuts = (a, b) => { +import { + WindowInfo, + Dispatch, + WindowPositions, + AppState, + WindowId +} from "../types"; +const abuts = (a: Box, b: Box) => { // TODO: This is kinda a hack. They should really be touching, not just within snapping distance. // Also, overlapping should not count. const wouldMoveTo = SnapUtils.snap(a, b); return wouldMoveTo.x !== undefined || wouldMoveTo.y !== undefined; }; -class WindowManager extends React.Component { +interface Props { + centerWindowsIfNeeded(container: HTMLElement): void; + container: HTMLElement; + windowsInfo: WindowInfo[]; + browserWindowSize: { height: number; width: number }; + updateWindowPositions(positions: WindowPositions, center: boolean): void; + getWindowHidden(windowId: WindowId): boolean; + windows: { [windowId: string]: ReactNode }; +} + +class WindowManager extends React.Component { componentDidMount() { this.props.centerWindowsIfNeeded(this.props.container); } @@ -25,12 +42,15 @@ class WindowManager extends React.Component { this.props.centerWindowsIfNeeded(this.props.container); } - movingAndStationaryNodes(key) { + movingAndStationaryNodes(key: WindowId): [WindowInfo[], WindowInfo[]] { const windows = this.props.windowsInfo.filter( w => this.props.windows[w.key] != null && !this.props.getWindowHidden(w.key) ); const targetNode = windows.find(node => node.key === key); + if (targetNode == null) { + throw new Error("Tried to move a node that does not exist"); + } let movingSet = new Set([targetNode]); // Only the main window brings other windows along. @@ -45,8 +65,8 @@ class WindowManager extends React.Component { return [moving, stationary]; } - handleMouseDown = (key, e) => { - if (!e.target.classList.contains("draggable")) { + handleMouseDown = (key: WindowId, e: React.MouseEvent) => { + if (!(e.target as HTMLElement).classList.contains("draggable")) { return; } // Prevent dragging from highlighting text. @@ -59,7 +79,7 @@ class WindowManager extends React.Component { const box = SnapUtils.boundingBox(moving); - const handleMouseMove = ee => { + const handleMouseMove = (ee: MouseEvent) => { const proposedDiff = { x: ee.clientX - mouseStart.x, y: ee.clientY - mouseStart.y @@ -91,10 +111,13 @@ class WindowManager extends React.Component { withinDiff ); - const windowPositionDiff = moving.reduce((diff, window) => { - diff[window.key] = SnapUtils.applyDiff(window, finalDiff); - return diff; - }, {}); + const windowPositionDiff = moving.reduce( + (diff: { [windowId: string]: Diff }, window) => { + diff[window.key] = SnapUtils.applyDiff(window, finalDiff); + return diff; + }, + {} + ); this.props.updateWindowPositions(windowPositionDiff, false); }; @@ -109,7 +132,7 @@ class WindowManager extends React.Component { }; render() { - const style = { + const style: React.CSSProperties = { position: "absolute", top: 0, left: 0 @@ -131,24 +154,19 @@ class WindowManager extends React.Component { } } -WindowManager.propTypes = { - windows: PropTypes.object.isRequired, - container: PropTypes.instanceOf(Element).isRequired -}; - -const mapStateToProps = state => ({ +const mapStateToProps = (state: AppState) => ({ windowsInfo: Selectors.getWindowsInfo(state), getWindowHidden: Selectors.getWindowHidden(state), getWindowOpen: Selectors.getWindowOpen(state), browserWindowSize: Selectors.getBrowserWindowSize(state) }); -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch: Dispatch) => { return { - updateWindowPositions: (positions, centered) => + updateWindowPositions: (positions: WindowPositions, centered: boolean) => dispatch(updateWindowPositions(positions, centered)), windowsHaveBeenCentered: () => dispatch(windowsHaveBeenCentered()), - centerWindowsIfNeeded: container => + centerWindowsIfNeeded: (container: HTMLElement) => dispatch(centerWindowsIfNeeded(container)) }; }; diff --git a/js/snapUtils.ts b/js/snapUtils.ts index 50555851..99eb1eb8 100644 --- a/js/snapUtils.ts +++ b/js/snapUtils.ts @@ -3,7 +3,7 @@ interface Point { y: number; } -interface Diff { +export interface Diff { x?: number; y?: number; } @@ -64,7 +64,7 @@ export const snap = (boxA: Box, boxB: Box) => { return { x, y }; }; -export const snapDiff = (a: Box, b: Box): Diff => { +export const snapDiff = (a: Box, b: Box): Point => { const newPos = snap(a, b); return { x: newPos.x === undefined ? 0 : newPos.x - a.x, @@ -73,7 +73,7 @@ export const snapDiff = (a: Box, b: Box): Diff => { }; // TODO: Use the first x and y combo -export const snapDiffManyToMany = (as: Box[], bs: Box[]): Diff => { +export const snapDiffManyToMany = (as: Box[], bs: Box[]): Point => { let x: number | undefined = 0; let y: number | undefined = 0; for (const a of as) { @@ -120,7 +120,7 @@ export const snapWithin = (boxA: Box, boundingBox: BoundingBox): Diff => { return { x, y }; }; -export const snapWithinDiff = (a: Box, b: Box) => { +export const snapWithinDiff = (a: Box, b: BoundingBox) => { const newPos = snapWithin(a, b); return { x: newPos.x === undefined ? 0 : newPos.x - a.x,