Move centerWindowsIfNeeded to an action creatorThis forces us to type it, as a nice side benefit

This commit is contained in:
Jordan Eldredge 2018-09-20 07:22:44 -07:00
parent 5fe64cdff8
commit b543447da9
5 changed files with 85 additions and 91 deletions

View file

@ -20,7 +20,8 @@ export {
toggleWindow,
updateWindowPositions,
toggleMainWindowShadeMode,
windowsHaveBeenCentered
windowsHaveBeenCentered,
centerWindowsIfNeeded
} from "./windows";
export {
play,

View file

@ -1,7 +1,10 @@
import {
getWindowGraph,
getWindowSizes,
getWindowPositions
getWindowPositions,
getWindowsInfo,
getWindowOpen,
getGenWindows
} from "../selectors";
import { objectMap } from "../utils";
@ -20,6 +23,9 @@ import { getPositionDiff, SizeDiff } from "../resizeUtils";
import { applyDiff } from "../snapUtils";
import { Action, Dispatchable, WindowId, WindowPositions } from "../types";
import { WINDOW_HEIGHT, WINDOW_WIDTH } from "../constants";
import { calculateBoundingBox } from "../utils";
// Dispatch an action and, if needed rearrange the windows to preserve
// the existing edge relationship.
//
@ -111,6 +117,70 @@ export function updateWindowPositions(
return { type: UPDATE_WINDOW_POSITIONS, positions, center };
}
export function windowsHaveBeenCentered() {
export function windowsHaveBeenCentered(): Dispatchable {
return { type: WINDOWS_HAVE_BEEN_CENTERED };
}
export function centerWindowsIfNeeded(container: HTMLElement): Dispatchable {
return (dispatch, getState) => {
const state = getState();
const { centerRequested } = state.windows;
if (!centerRequested) {
return;
}
const genWindows = getGenWindows(state);
const windowsInfo = getWindowsInfo(state);
const getOpen = getWindowOpen(state);
const rect = container.getBoundingClientRect();
const offsetLeft = rect.left + window.scrollX;
const offsetTop = rect.top + window.scrollY;
const width = container.scrollWidth;
const height = container.scrollHeight;
if (windowsInfo.some(w => w.x == null || w.y == null)) {
// Some windows do not have an initial position, so we'll come up
// with your own layout.
const windowPositions: WindowPositions = {};
const keys: string[] = Object.keys(genWindows).filter(
windowId => genWindows[windowId].open
);
const totalHeight = keys.length * WINDOW_HEIGHT;
const globalOffsetLeft = Math.max(0, width / 2 - WINDOW_WIDTH / 2);
const globalOffsetTop = Math.max(0, height / 2 - totalHeight / 2);
keys.forEach((key, i) => {
const offset = WINDOW_HEIGHT * i;
windowPositions[key] = {
x: Math.ceil(offsetLeft + globalOffsetLeft),
y: Math.ceil(offsetTop + (globalOffsetTop + offset))
};
});
dispatch(updateWindowPositions(windowPositions, false));
} else {
// A layout has been suplied. We will compute the bounding box and
// center the given layout.
const bounding = calculateBoundingBox(
windowsInfo.filter(w => getOpen(w.key))
);
const boxHeight = bounding.bottom - bounding.top;
const boxWidth = bounding.right - bounding.left;
const move = {
x: Math.ceil(offsetLeft - bounding.left + (width - boxWidth) / 2),
y: Math.ceil(offsetTop - bounding.top + (height - boxHeight) / 2)
};
const newPositions = windowsInfo.reduce(
(pos, w) => ({
...pos,
[w.key]: { x: move.x + w.x, y: move.y + w.y }
}),
{}
);
dispatch(updateWindowPositions(newPositions, false));
}
dispatch(windowsHaveBeenCentered());
};
}

View file

@ -11,19 +11,12 @@ import {
applyDiff,
applyMultipleDiffs
} from "../snapUtils";
import {
getWindowsInfo,
getWindowHidden,
getWindowOpen,
getCenterRequested
} from "../selectors";
import { getWindowsInfo, getWindowHidden, getWindowOpen } from "../selectors";
import {
updateWindowPositions,
windowsHaveBeenCentered
windowsHaveBeenCentered,
centerWindowsIfNeeded
} from "../actionCreators";
import { WINDOW_HEIGHT, WINDOW_WIDTH } from "../constants";
import { calculateBoundingBox } from "../utils";
const abuts = (a, b) => {
// TODO: This is kinda a hack. They should really be touching, not just within snapping distance.
// Also, overlapping should not count.
@ -33,65 +26,9 @@ const abuts = (a, b) => {
class WindowManager extends React.Component {
componentDidMount() {
this.centerWindowsIfNeeded();
this.props.centerWindowsIfNeeded(this.props.container);
}
centerWindowsIfNeeded = () => {
const { container, centerRequested } = this.props;
if (!centerRequested) {
return;
}
const rect = container.getBoundingClientRect();
const offsetLeft = rect.left + window.scrollX;
const offsetTop = rect.top + window.scrollY;
const width = container.scrollWidth;
const height = container.scrollHeight;
if (this.props.windowsInfo.some(w => w.x == null || w.y == null)) {
// Some windows do not have an initial position, so we'll come up
// with your own layout.
const windowPositions = {};
const keys = this.windowKeys();
const totalHeight = keys.length * WINDOW_HEIGHT;
const globalOffsetLeft = Math.max(0, width / 2 - WINDOW_WIDTH / 2);
const globalOffsetTop = Math.max(0, height / 2 - totalHeight / 2);
keys.forEach((key, i) => {
const offset = WINDOW_HEIGHT * i;
windowPositions[key] = {
x: Math.ceil(offsetLeft + globalOffsetLeft),
y: Math.ceil(offsetTop + (globalOffsetTop + offset))
};
});
this.props.updateWindowPositions(windowPositions, false);
} else {
// A layout has been suplied. We will compute the bounding box and
// center the given layout.
const bounding = calculateBoundingBox(
this.props.windowsInfo.filter(w => this.props.getWindowOpen(w.key))
);
const boxHeight = bounding.bottom - bounding.top;
const boxWidth = bounding.right - bounding.left;
const move = {
x: Math.ceil(offsetLeft - bounding.left + (width - boxWidth) / 2),
y: Math.ceil(offsetTop - bounding.top + (height - boxHeight) / 2)
};
const newPositions = this.props.windowsInfo.reduce(
(pos, w) => ({
...pos,
[w.key]: { x: move.x + w.x, y: move.y + w.y }
}),
{}
);
this.props.updateWindowPositions(newPositions, false);
}
this.props.windowsHaveBeenCentered();
};
movingAndStationaryNodes(key) {
const windows = this.props.windowsInfo.filter(
w =>
@ -183,14 +120,6 @@ class WindowManager extends React.Component {
window.addEventListener("mousemove", handleMouseMove);
};
// Keys for the visible windows
windowKeys() {
// TODO: Iterables can probably do this better.
return Object.keys(this.props.windows).filter(
key => !!this.props.windows[key]
);
}
render() {
const style = {
position: "absolute",
@ -222,15 +151,16 @@ WindowManager.propTypes = {
const mapStateToProps = state => ({
windowsInfo: getWindowsInfo(state),
getWindowHidden: getWindowHidden(state),
getWindowOpen: getWindowOpen(state),
centerRequested: getCenterRequested(state)
getWindowOpen: getWindowOpen(state)
});
const mapDispatchToProps = dispatch => {
return {
updateWindowPositions: (positions, centered) =>
dispatch(updateWindowPositions(positions, centered)),
windowsHaveBeenCentered: () => dispatch(windowsHaveBeenCentered())
windowsHaveBeenCentered: () => dispatch(windowsHaveBeenCentered()),
centerWindowsIfNeeded: container =>
dispatch(centerWindowsIfNeeded(container))
};
};

View file

@ -342,6 +342,7 @@ export type Action =
| {
type: "MINIMIZE_WINAMP";
}
| { type: "WINDOWS_HAVE_BEEN_CENTERED" }
| {
type: "CLOSE_REQUESTED";
cancel: () => void;

View file

@ -1,4 +1,5 @@
import { DEFAULT_SKIN } from "./constants";
import { WindowInfo } from "./types";
interface Time {
minutesFirstDigit: string;
@ -318,16 +319,7 @@ export function objectFilter<V>(
}, {});
}
interface Window {
left: number;
top: number;
x: number;
y: number;
width: number;
height: number;
}
export const calculateBoundingBox = (windows: Window[]) =>
export const calculateBoundingBox = (windows: WindowInfo[]) =>
windows
.map(w => ({
left: w.x,