mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-22 01:29:22 +00:00
Move centerWindowsIfNeeded to an action creatorThis forces us to type it, as a nice side benefit
This commit is contained in:
parent
5fe64cdff8
commit
b543447da9
5 changed files with 85 additions and 91 deletions
|
|
@ -20,7 +20,8 @@ export {
|
|||
toggleWindow,
|
||||
updateWindowPositions,
|
||||
toggleMainWindowShadeMode,
|
||||
windowsHaveBeenCentered
|
||||
windowsHaveBeenCentered,
|
||||
centerWindowsIfNeeded
|
||||
} from "./windows";
|
||||
export {
|
||||
play,
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -342,6 +342,7 @@ export type Action =
|
|||
| {
|
||||
type: "MINIMIZE_WINAMP";
|
||||
}
|
||||
| { type: "WINDOWS_HAVE_BEEN_CENTERED" }
|
||||
| {
|
||||
type: "CLOSE_REQUESTED";
|
||||
cancel: () => void;
|
||||
|
|
|
|||
12
js/utils.ts
12
js/utils.ts
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue