Progress toward unifying windows

This commit is contained in:
Jordan Eldredge 2018-05-11 21:39:28 -07:00
parent 6125a0b5d4
commit 2d1bd3f110
14 changed files with 159 additions and 153 deletions

View file

@ -45,7 +45,6 @@ import {
SET_EQ_ON,
SET_EQ_OFF,
TOGGLE_EQUALIZER_SHADE_MODE,
CLOSE_EQUALIZER_WINDOW,
REMOVE_TRACKS,
REMOVE_ALL_TRACKS,
PLAY,
@ -66,7 +65,9 @@ import {
MEDIA_TAG_REQUEST_FAILED,
UPDATE_WINDOW_POSITIONS,
TOGGLE_DOUBLESIZE_MODE,
WINDOW_SIZE_CHANGED
WINDOW_SIZE_CHANGED,
TOGGLE_WINDOW,
CLOSE_WINDOW
} from "./actionTypes";
import LoadQueue from "./loadQueue";
@ -537,8 +538,8 @@ export function togglePlaylistShadeMode() {
return withWindowGraphIntegrity({ type: TOGGLE_PLAYLIST_SHADE_MODE });
}
export function closeEqualizerWindow() {
return { type: CLOSE_EQUALIZER_WINDOW };
export function closeWindow(windowId) {
return { type: CLOSE_WINDOW, windowId };
}
export function cropPlaylist() {
@ -603,6 +604,10 @@ export function setWindowSize(windowId, size) {
return { type: WINDOW_SIZE_CHANGED, windowId, size };
}
export function toggleWindow(windowId) {
return { type: TOGGLE_WINDOW, windowId };
}
export function scrollNTracks(n) {
return (dispatch, getState) => {
const state = getState();

View file

@ -1,7 +1,6 @@
export const ADD_TRACK_FROM_URL = "ADD_TRACK_FROM_URL";
export const CLOSE_WINAMP = "CLOSE_WINAMP";
export const MINIMIZE_WINAMP = "MINIMIZE_WINAMP";
export const CLOSE_EQUALIZER_WINDOW = "CLOSE_EQUALIZER_WINDOW";
export const IS_PLAYING = "IS_PLAYING";
export const IS_STOPPED = "IS_STOPPED";
export const PAUSE = "PAUSE";
@ -21,9 +20,6 @@ export const STEP_MARQUEE = "STEP_MARQUEE";
export const STOP = "STOP";
export const STOP_WORKING = "STOP_WORKING";
export const TOGGLE_DOUBLESIZE_MODE = "TOGGLE_DOUBLESIZE_MODE";
export const TOGGLE_MAIN_WINDOW = "TOGGLE_MAIN_WINDOW";
export const TOGGLE_EQUALIZER_WINDOW = "TOGGLE_EQUALIZER_WINDOW";
export const TOGGLE_PLAYLIST_WINDOW = "TOGGLE_PLAYLIST_WINDOW";
export const SET_EQ_AUTO = "SET_EQ_AUTO";
export const SET_EQ_ON = "SET_EQ_ON";
export const SET_EQ_OFF = "SET_EQ_OFF";
@ -59,10 +55,9 @@ export const BUFFER_TRACK = "BUFFER_TRACK";
export const DRAG_SELECTED = "DRAG_SELECTED";
export const SET_MEDIA_TAGS = "SET_MEDIA_TAGS";
export const SET_MEDIA_DURATION = "SET_MEDIA_DURATION";
export const TOGGLE_GEN_WINDOW = "TOGGLE_GEN_WINDOW";
export const OPEN_GEN_WINDOW = "OPEN_GEN_WINDOW";
export const TOGGLE_WINDOW = "TOGGLE_WINDOW";
export const ADD_GEN_WINDOW = "ADD_GEN_WINDOW";
export const CLOSE_GEN_WINDOW = "CLOSE_GEN_WINDOW";
export const CLOSE_WINDOW = "CLOSE_WINDOW";
export const MEDIA_TAG_REQUEST_INITIALIZED = "MEDIA_TAG_REQUEST_INITIALIZED";
export const MEDIA_TAG_REQUEST_FAILED = "MEDIA_TAG_REQUEST_FAILED";
export const NETWORK_CONNECTED = "NETWORK_CONNECTED";

View file

@ -1,6 +1,7 @@
import React from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { objectMap } from "../utils";
import ContextMenuWrapper from "./ContextMenuWrapper";
import MainContextMenu from "./MainWindow/MainContextMenu";
import WindowManager from "./WindowManager";
@ -15,9 +16,6 @@ import "../../css/webamp.css";
const App = ({
media,
closed,
mainWindow,
equalizer,
playlist,
genWindowsInfo,
container,
filePickers,
@ -26,30 +24,44 @@ const App = ({
if (closed) {
return null;
}
const windows = {
main: mainWindow && (
<MainWindow mediaPlayer={media} filePickers={filePickers} />
),
equalizer: equalizer && <EqualizerWindow />,
playlist: playlist && <PlaylistWindow />
};
// Add any "generic" windows
genWindows.forEach(genWindow => {
const { id, title, Component } = genWindow;
if (genWindowsInfo[id].open) {
windows[id] = (
<GenWindow key={id} title={title} windowId={id}>
{({ height, width }) => (
<Component
analyser={media._analyser}
width={width}
height={height}
/>
)}
</GenWindow>
);
// Index genWindows by id
const genWindowComponents = genWindows.reduce(
(comps, gen) => ({ ...comps, [gen.id]: gen }),
{}
);
const windows = objectMap(genWindowsInfo, (w, id) => {
switch (id) {
case "main":
return (
w.open && <MainWindow mediaPlayer={media} filePickers={filePickers} />
);
case "equalizer":
return w.open && <EqualizerWindow />;
case "playlist":
return w.open && <PlaylistWindow />;
default:
if (!w.generic) {
throw new Error("Tried to render an unknown window:", id);
}
const { Component, title } = genWindowComponents[id];
return (
w.open && (
<GenWindow title={title} windowId={id}>
{({ height, width }) => (
<Component
analyser={media._analyser}
width={width}
height={height}
/>
)}
</GenWindow>
)
);
}
});
return (
<div role="application" id="webamp">
<Skin />
@ -70,7 +82,6 @@ const mapStateToProps = state => ({
closed: state.display.closed,
mainWindow: state.windows.mainWindow,
equalizer: state.windows.equalizer,
playlist: state.windows.playlist,
genWindowsInfo: state.windows.genWindows
});

View file

@ -4,10 +4,7 @@ import Volume from "../Volume";
import Balance from "../Balance";
import { segment } from "../../utils";
import {
closeEqualizerWindow,
toggleEqualizerShadeMode
} from "../../actionCreators";
import { closeWindow, toggleEqualizerShadeMode } from "../../actionCreators";
const EqualizerShade = props => {
const { volume, balance } = props;
@ -30,7 +27,7 @@ const EqualizerShade = props => {
};
const mapDispatchToProps = {
closeEqualizerWindow,
closeWindow: () => closeWindow("equalizer"),
toggleEqualizerShadeMode
};

View file

@ -10,7 +10,7 @@ import {
setEqToMax,
setEqToMid,
setEqToMin,
closeEqualizerWindow,
closeWindow,
toggleEqualizerShadeMode,
scrollVolume
} from "../../actionCreators";
@ -87,6 +87,7 @@ EqualizerWindow.propTypes = {
shade: PropTypes.bool.isRequired
};
// TODO: Convert to object shorthand
const mapDispatchToProps = dispatch => ({
focusWindow: () =>
dispatch({ type: SET_FOCUSED_WINDOW, window: WINDOWS.EQUALIZER }),
@ -95,7 +96,7 @@ const mapDispatchToProps = dispatch => ({
setEqToMid: () => dispatch(setEqToMid()),
setEqToMax: () => dispatch(setEqToMax()),
setHertzValue: hertz => value => dispatch(setEqBand(hertz, value)),
closeEqualizerWindow: () => dispatch(closeEqualizerWindow()),
closeEqualizerWindow: () => dispatch(closeWindow("equalizer")),
toggleEqualizerShadeMode: () => dispatch(toggleEqualizerShadeMode()),
scrollVolume: e => dispatch(scrollVolume(e))
});

View file

@ -4,8 +4,8 @@ import PropTypes from "prop-types";
import classnames from "classnames";
import "../../../css/gen-window.css";
import { SET_FOCUSED_WINDOW, CLOSE_GEN_WINDOW } from "../../actionTypes";
import { scrollVolume, setWindowSize } from "../../actionCreators";
import { SET_FOCUSED_WINDOW } from "../../actionTypes";
import { scrollVolume, setWindowSize, closeWindow } from "../../actionCreators";
import { getWindowPixelSize } from "../../selectors";
import ResizeTarget from "../ResizeTarget";
@ -34,9 +34,10 @@ export const GenWindow = ({
windowId,
windowSize,
setGenWindowSize,
scrollVolume: handleWheel
scrollVolume: handleWheel,
width,
height
}) => {
const { width, height } = getWindowPixelSize(windowSize);
return (
<div
className={classnames("gen-window", "window", { selected })}
@ -93,14 +94,19 @@ GenWindow.propTypes = {
selected: PropTypes.bool.isRequired
};
const mapStateToProps = (state, ownProps) => ({
selected: state.windows.focused === ownProps.windowId,
windowSize: state.windows.genWindows[ownProps.windowId].size
});
const mapStateToProps = (state, ownProps) => {
const { width, height } = getWindowPixelSize(state, ownProps.windowId);
return {
width,
height,
selected: state.windows.focused === ownProps.windowId,
windowSize: state.windows.genWindows[ownProps.windowId].size
};
};
const mapDispatchToProps = {
setFocus: windowId => ({ type: SET_FOCUSED_WINDOW, window: windowId }),
close: windowId => ({ type: CLOSE_GEN_WINDOW, windowId }),
close: windowId => closeWindow(windowId),
setGenWindowSize: setWindowSize,
scrollVolume
};

View file

@ -2,7 +2,7 @@ import React from "react";
import { connect } from "react-redux";
import classnames from "classnames";
import { TOGGLE_EQUALIZER_WINDOW } from "../../actionTypes";
import { toggleWindow } from "../../actionCreators";
const EqToggleButton = props => (
<div
@ -17,8 +17,8 @@ const mapStateToProps = state => ({
equalizer: state.windows.equalizer
});
const mapDispatchToProps = dispatch => ({
handleClick: () => dispatch({ type: TOGGLE_EQUALIZER_WINDOW })
});
const mapDispatchToProps = {
handleClick: () => toggleWindow("equalizer")
};
export default connect(mapStateToProps, mapDispatchToProps)(EqToggleButton);

View file

@ -3,14 +3,9 @@ import { connect } from "react-redux";
import {
close,
openMediaFileDialog,
loadMediaFiles
loadMediaFiles,
toggleWindow
} from "../../actionCreators";
import {
TOGGLE_MAIN_WINDOW,
TOGGLE_EQUALIZER_WINDOW,
TOGGLE_PLAYLIST_WINDOW,
TOGGLE_GEN_WINDOW
} from "../../actionTypes";
import { getGenWindows } from "../../selectors";
import { LOAD_STYLE } from "../../constants";
import { Hr, Node, Parent, LinkNode } from "../ContextMenu";
@ -97,10 +92,10 @@ const mapDispatchToProps = {
close,
openMediaFileDialog,
loadMediaFiles,
toggleMainWindow: () => ({ type: TOGGLE_MAIN_WINDOW }),
togglePlaylist: () => ({ type: TOGGLE_PLAYLIST_WINDOW }),
toggleEqualizer: () => ({ type: TOGGLE_EQUALIZER_WINDOW }),
toggleGenWindow: windowId => ({ type: TOGGLE_GEN_WINDOW, windowId })
toggleMainWindow: () => toggleWindow("main"),
togglePlaylist: () => toggleWindow("playlist"),
toggleEqualizer: () => toggleWindow("equalizer"),
toggleGenWindow: toggleWindow
};
export default connect(mapStateToProps, mapDispatchToProps)(MainContextMenu);

View file

@ -2,7 +2,7 @@ import React from "react";
import { connect } from "react-redux";
import classnames from "classnames";
import { TOGGLE_PLAYLIST_WINDOW } from "../../actionTypes";
import { toggleWindow } from "../../actionCreators";
const PlaylistToggleButton = props => (
<div
@ -18,7 +18,7 @@ const mapStateToProps = state => ({
});
const mapDispatchToProps = {
handleClick: () => ({ type: TOGGLE_PLAYLIST_WINDOW })
handleClick: () => toggleWindow("playlist")
};
export default connect(mapStateToProps, mapDispatchToProps)(

View file

@ -1,9 +1,13 @@
import React from "react";
import { connect } from "react-redux";
import classnames from "classnames";
import { getOrderedTracks, getMinimalMediaText } from "../../selectors";
import {
getOrderedTracks,
getMinimalMediaText,
getWindowSize
} from "../../selectors";
import { getTimeStr } from "../../utils";
import { TOGGLE_PLAYLIST_WINDOW, SET_FOCUSED_WINDOW } from "../../actionTypes";
import { SET_FOCUSED_WINDOW } from "../../actionTypes";
import {
WINDOWS,
@ -12,7 +16,7 @@ import {
CHARACTER_WIDTH,
UTF8_ELLIPSIS
} from "../../constants";
import { togglePlaylistShadeMode } from "../../actionCreators";
import { togglePlaylistShadeMode, closeWindow } from "../../actionCreators";
import CharacterString from "../CharacterString";
import PlaylistResizeTarget from "./PlaylistResizeTarget";
@ -79,20 +83,20 @@ class PlaylistShade extends React.Component {
const mapDispatchToProps = dispatch => ({
focusPlaylist: () =>
dispatch({ type: SET_FOCUSED_WINDOW, window: WINDOWS.PLAYLIST }),
close: () => dispatch({ type: TOGGLE_PLAYLIST_WINDOW }),
close: () => closeWindow("playlist"),
toggleShade: () => dispatch(togglePlaylistShadeMode())
});
const mapStateToProps = state => {
const {
windows: { focused },
display: { skinPlaylistStyle, playlistSize, playlistShade },
display: { skinPlaylistStyle, playlistShade },
media: { length }
} = state;
return {
focused,
skinPlaylistStyle,
playlistSize,
playlistSize: getWindowSize(state, "playlist"),
playlistShade,
trackOrder: getOrderedTracks(state),
length,

View file

@ -3,14 +3,15 @@ import { connect } from "react-redux";
import classnames from "classnames";
import { WINDOWS, TRACK_HEIGHT } from "../../constants";
import { TOGGLE_PLAYLIST_WINDOW, SET_FOCUSED_WINDOW } from "../../actionTypes";
import { SET_FOCUSED_WINDOW } from "../../actionTypes";
import {
toggleVisualizerStyle,
scrollUpFourTracks,
scrollDownFourTracks,
loadFilesFromReferences,
togglePlaylistShadeMode,
scrollVolume
scrollVolume,
closeWindow
} from "../../actionCreators";
import {
getScrollOffset,
@ -152,7 +153,7 @@ const mapDispatchToProps = {
type: SET_FOCUSED_WINDOW,
window: WINDOWS.PLAYLIST
}),
close: () => ({ type: TOGGLE_PLAYLIST_WINDOW }),
close: () => closeWindow("playlist"),
toggleShade: togglePlaylistShadeMode,
toggleVisualizerStyle,
scrollUpFourTracks,

View file

@ -12,16 +12,11 @@ import {
nextN,
next,
previous,
toggleDoubleSizeMode
toggleDoubleSizeMode,
toggleWindow
} from "./actionCreators";
import {
TOGGLE_TIME_MODE,
TOGGLE_LLAMA_MODE,
TOGGLE_MAIN_WINDOW,
TOGGLE_PLAYLIST_WINDOW,
TOGGLE_EQUALIZER_WINDOW
} from "./actionTypes";
import { TOGGLE_TIME_MODE, TOGGLE_LLAMA_MODE } from "./actionTypes";
import { arraysAreEqual } from "./utils";
@ -56,13 +51,13 @@ export default function(dispatch) {
} else if (e.altKey) {
switch (e.keyCode) {
case 87: // ALT+W
dispatch({ type: TOGGLE_MAIN_WINDOW });
dispatch(toggleWindow("main"));
break;
case 69: // ALT+E
dispatch({ type: TOGGLE_PLAYLIST_WINDOW });
dispatch(toggleWindow("playlist"));
break;
case 71: // ALT+G
dispatch({ type: TOGGLE_EQUALIZER_WINDOW });
dispatch(toggleWindow("equalizer"));
break;
}
} else {

View file

@ -1,13 +1,8 @@
import { WINDOWS } from "../constants";
import {
SET_FOCUSED_WINDOW,
TOGGLE_MAIN_WINDOW,
TOGGLE_EQUALIZER_WINDOW,
CLOSE_EQUALIZER_WINDOW,
TOGGLE_PLAYLIST_WINDOW,
TOGGLE_GEN_WINDOW,
CLOSE_GEN_WINDOW,
OPEN_GEN_WINDOW,
TOGGLE_WINDOW,
CLOSE_WINDOW,
ADD_GEN_WINDOW,
UPDATE_WINDOW_POSITIONS,
WINDOW_SIZE_CHANGED
@ -15,12 +10,34 @@ import {
const defaultWindowsState = {
focused: WINDOWS.MAIN,
mainWindow: true,
equalizer: true,
playlist: true,
genWindows: {
// TODO: Remove static capabilites and derive them from ids/generic
main: {
size: [0, 0],
open: true,
shade: false,
canResize: false,
canShade: true,
canDouble: true,
generic: false
},
equalizer: {
size: [0, 0],
open: true,
shade: false,
canResize: false,
canShade: true,
canDouble: true,
generic: false
},
playlist: {
size: [0, 0]
size: [0, 0],
open: true,
shade: false,
canResize: true,
canShade: true,
canDouble: false,
generic: false
}
},
positions: {}
@ -30,15 +47,7 @@ const windows = (state = defaultWindowsState, action) => {
switch (action.type) {
case SET_FOCUSED_WINDOW:
return { ...state, focused: action.window };
case TOGGLE_MAIN_WINDOW:
return { ...state, mainWindow: !state.mainWindow };
case TOGGLE_EQUALIZER_WINDOW:
return { ...state, equalizer: !state.equalizer };
case CLOSE_EQUALIZER_WINDOW:
return { ...state, equalizer: false };
case TOGGLE_PLAYLIST_WINDOW:
return { ...state, playlist: !state.playlist };
case TOGGLE_GEN_WINDOW:
case TOGGLE_WINDOW:
return {
...state,
genWindows: {
@ -49,7 +58,7 @@ const windows = (state = defaultWindowsState, action) => {
}
}
};
case CLOSE_GEN_WINDOW:
case CLOSE_WINDOW:
return {
...state,
genWindows: {
@ -61,25 +70,29 @@ const windows = (state = defaultWindowsState, action) => {
}
};
case ADD_GEN_WINDOW:
return {
...state,
genWindows: {
...state.genWindows,
[action.windowId]: { title: action.title, open: true, size: [0, 0] }
}
};
case OPEN_GEN_WINDOW:
return {
...state,
genWindows: {
...state.genWindows,
[action.windowId]: {
...state.genWindows[action.windowId],
open: true
title: action.title,
open: true,
size: [0, 0],
canShade: false,
canResize: true,
canDouble: false,
generic: true
}
}
};
case WINDOW_SIZE_CHANGED:
const { canResize } = state.genWindows[action.windowId];
if (!canResize) {
throw new Error(
"Tried to resize a window that cannot be resized:",
action.windowId
);
}
return {
...state,
genWindows: {

View file

@ -125,7 +125,7 @@ export const nextTrack = (state, n = 1) => {
const BASE_WINDOW_HEIGHT = 58;
export const getNumberOfVisibleTracks = state => {
const playlistSize = getWindowSize(state, "playlist", state);
const playlistSize = getWindowSize(state, "playlist");
return Math.floor(
(BASE_WINDOW_HEIGHT + WINDOW_RESIZE_SEGMENT_HEIGHT * playlistSize[1]) /
TRACK_HEIGHT
@ -252,17 +252,21 @@ export function getWindowPositions(state) {
}
const WINDOW_HEIGHT = 116;
const DEFAUT_WINDOW_SIZE = {
height: WINDOW_HEIGHT,
width: WINDOW_WIDTH
};
const SHADE_WINDOW_HEIGHT = 14;
export function getWindowPixelSize([width, height]) {
return {
// TODO: Clean this up.
export function getWindowPixelSize(state, windowId) {
const w = state.windows.genWindows[windowId];
const [width, height] = w.size;
const doubledMultiplier = state.display.doubled && w.canDouble ? 2 : 1;
const pix = {
height: WINDOW_HEIGHT + height * WINDOW_RESIZE_SEGMENT_HEIGHT,
width: WINDOW_WIDTH + width * WINDOW_RESIZE_SEGMENT_WIDTH
};
return {
height: (w.shade ? SHADE_WINDOW_HEIGHT : pix.height) * doubledMultiplier,
width: pix.width * doubledMultiplier
};
}
export function getWindowSize(state, windowId) {
@ -270,34 +274,13 @@ export function getWindowSize(state, windowId) {
}
export function getPlaylistWindowPixelSize(state) {
return getWindowPixelSize(getWindowSize(state, "playlist"));
}
function getGenericWindowSize(size, shade, doubled) {
const doubledMultiplier = doubled ? 2 : 1;
return {
height: (shade ? SHADE_WINDOW_HEIGHT : size.height) * doubledMultiplier,
width: size.width * doubledMultiplier
};
return getWindowPixelSize(state, "playlist");
}
export function getWindowSizes(state) {
const { doubled, mainShade, equalizerShade, playlistShade } = state.display;
const main = getGenericWindowSize(DEFAUT_WINDOW_SIZE, mainShade, doubled);
const equalizer = getGenericWindowSize(
DEFAUT_WINDOW_SIZE,
equalizerShade,
doubled
);
const playlist = getGenericWindowSize(
getPlaylistWindowPixelSize(state),
playlistShade,
false // The playlist cannot be doubled
);
const genWindowSizes = objectMap(state.windows.genWindows, genWindow =>
getWindowPixelSize(genWindow.size)
);
return { main, equalizer, playlist, ...genWindowSizes };
return objectMap(state.windows.genWindows, (w, windowId) => {
return getWindowPixelSize(state, windowId);
});
}
export const getWindowsInfo = createSelector(