mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-20 16:49:52 +00:00
Type some more stuff
This commit is contained in:
parent
02bd19e75f
commit
c05099fd8f
8 changed files with 140 additions and 105 deletions
|
|
@ -143,7 +143,7 @@ export function loadSerializedState(
|
|||
};
|
||||
}
|
||||
|
||||
export function loadDefaultSkin() {
|
||||
export function loadDefaultSkin(): Dispatchable {
|
||||
return { type: LOAD_DEFAULT_SKIN };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
import React from "react";
|
||||
import GenWindow from "../GenWindow";
|
||||
import "../../../css/gen-window.css";
|
||||
|
||||
const AvsWindow = () => (
|
||||
<GenWindow title="Avs" close={() => {}} windowId="AVS_WINDOW">
|
||||
<canvas
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: "100%",
|
||||
width: "100%"
|
||||
}}
|
||||
/>
|
||||
</GenWindow>
|
||||
);
|
||||
|
||||
export default AvsWindow;
|
||||
|
|
@ -1,9 +1,18 @@
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { ReactNode } from "react";
|
||||
import ContextMenu from "./ContextMenu";
|
||||
|
||||
export default class ContextMenuWraper extends React.Component {
|
||||
constructor(props) {
|
||||
interface Props {
|
||||
renderContents(): ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
selected: boolean;
|
||||
offsetTop: number | null;
|
||||
offsetLeft: number | null;
|
||||
}
|
||||
|
||||
export default class ContextMenuWraper extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selected: false,
|
||||
|
|
@ -29,14 +38,14 @@ export default class ContextMenuWraper extends React.Component {
|
|||
this._closeMenu();
|
||||
};
|
||||
|
||||
_handleGlobalClick = e => {
|
||||
_handleGlobalClick = (e: MouseEvent) => {
|
||||
if (e.button === 2) {
|
||||
return;
|
||||
}
|
||||
this._closeMenu();
|
||||
};
|
||||
|
||||
_handleRightClick = e => {
|
||||
_handleRightClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const { pageX, pageY } = e;
|
||||
this.setState({
|
||||
selected: true,
|
||||
|
|
@ -63,8 +72,8 @@ export default class ContextMenuWraper extends React.Component {
|
|||
>
|
||||
<ContextMenu
|
||||
selected={this.state.selected}
|
||||
offsetTop={this.state.offsetTop}
|
||||
offsetLeft={this.state.offsetLeft}
|
||||
offsetTop={this.state.offsetTop || 0}
|
||||
offsetLeft={this.state.offsetLeft || 0}
|
||||
>
|
||||
{renderContents()}
|
||||
</ContextMenu>
|
||||
|
|
@ -73,8 +82,3 @@ export default class ContextMenuWraper extends React.Component {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
ContextMenuWraper.propTypes = {
|
||||
children: PropTypes.any.isRequired,
|
||||
renderContents: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
@ -1,17 +1,34 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import Slider from "rc-slider/lib/Slider";
|
||||
import Slider from "rc-slider";
|
||||
import { SET_BAND_FOCUS, UNSET_FOCUS } from "../../actionTypes";
|
||||
import { AppState, Dispatch, Band as BandType } from "../../types";
|
||||
|
||||
interface StateProps {
|
||||
value: number;
|
||||
backgroundPosition: string;
|
||||
}
|
||||
interface DispatchProps {
|
||||
handleMouseDown(): void;
|
||||
handleMouseUp(): void;
|
||||
}
|
||||
interface OwnProps {
|
||||
id: string;
|
||||
band: BandType;
|
||||
onChange(value: number): void;
|
||||
}
|
||||
|
||||
type Props = StateProps & DispatchProps & OwnProps;
|
||||
|
||||
const MAX_VALUE = 100;
|
||||
// Given a value between 1-100, return the sprite number (0-27)
|
||||
export const spriteNumber = value => {
|
||||
export const spriteNumber = (value: number): number => {
|
||||
const percent = value / 100;
|
||||
return Math.round(percent * 27);
|
||||
};
|
||||
|
||||
// Given a sprite number, return the x,y
|
||||
export const spriteOffsets = number => {
|
||||
export const spriteOffsets = (number: number): { x: number; y: number } => {
|
||||
const x = number % 14;
|
||||
const y = Math.floor(number / 14);
|
||||
return { x, y };
|
||||
|
|
@ -26,10 +43,9 @@ const Band = ({
|
|||
onChange,
|
||||
handleMouseDown,
|
||||
handleMouseUp
|
||||
}) => (
|
||||
}: Props) => (
|
||||
<div id={id} className="band" style={{ backgroundPosition }}>
|
||||
<Slider
|
||||
type="range"
|
||||
min={1}
|
||||
max={MAX_VALUE}
|
||||
step={1}
|
||||
|
|
@ -43,20 +59,19 @@ const Band = ({
|
|||
</div>
|
||||
);
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const mapStateToProps = (state: AppState, ownProps: OwnProps): StateProps => {
|
||||
const value = state.equalizer.sliders[ownProps.band];
|
||||
const { x, y } = spriteOffsets(spriteNumber(value));
|
||||
const xOffset = x * 15; // Each sprite is 15px wide
|
||||
const yOffset = y * 65; // Each sprite is 15px tall
|
||||
const backgroundPosition = `-${xOffset}px -${yOffset}px`;
|
||||
return {
|
||||
id: ownProps.id,
|
||||
value,
|
||||
backgroundPosition
|
||||
};
|
||||
return { value, backgroundPosition };
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch, ownProps) => ({
|
||||
const mapDispatchToProps = (
|
||||
dispatch: Dispatch,
|
||||
ownProps: OwnProps
|
||||
): DispatchProps => ({
|
||||
handleMouseDown: () =>
|
||||
dispatch({ type: SET_BAND_FOCUS, input: "eq", bandFocused: ownProps.band }),
|
||||
handleMouseUp: () => dispatch({ type: UNSET_FOCUS })
|
||||
|
|
@ -4,18 +4,29 @@ import classnames from "classnames";
|
|||
|
||||
import { getWindowOpen } from "../../selectors";
|
||||
import { toggleWindow } from "../../actionCreators";
|
||||
import { AppState } from "../../types";
|
||||
|
||||
const EqToggleButton = props => (
|
||||
interface StateProps {
|
||||
windowOpen: boolean;
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
handleClick(e: React.MouseEvent<HTMLDivElement>): void;
|
||||
}
|
||||
|
||||
type Props = StateProps & DispatchProps;
|
||||
|
||||
const EqToggleButton = (props: Props) => (
|
||||
<div
|
||||
id="equalizer-button"
|
||||
className={classnames({ selected: props.getWindowOpen("equalizer") })}
|
||||
className={classnames({ selected: props.windowOpen })}
|
||||
onClick={props.handleClick}
|
||||
title="Toggle Graphical Equalizer"
|
||||
/>
|
||||
);
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
getWindowOpen: getWindowOpen(state)
|
||||
const mapStateToProps = (state: AppState): StateProps => ({
|
||||
windowOpen: getWindowOpen(state)("equalizer")
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
|
|
@ -1,18 +1,21 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import {
|
||||
previous,
|
||||
play,
|
||||
pause,
|
||||
stop,
|
||||
next,
|
||||
seekForward,
|
||||
seekBackward,
|
||||
nextN
|
||||
} from "../actionCreators";
|
||||
import * as Actions from "../actionCreators";
|
||||
import { Hr, Node } from "./ContextMenu";
|
||||
import { Dispatch } from "../types";
|
||||
|
||||
const PlaybackContextMenu = props => (
|
||||
interface Props {
|
||||
previous(): void;
|
||||
play(): void;
|
||||
pause(): void;
|
||||
stop(): void;
|
||||
next(): void;
|
||||
seekBackward(steps: number): void;
|
||||
seekForward(steps: number): void;
|
||||
nextN(steps: number): void;
|
||||
}
|
||||
|
||||
const PlaybackContextMenu = (props: Props) => (
|
||||
<React.Fragment>
|
||||
<Node label="Previous" hotkey="Z" onClick={props.previous} />
|
||||
<Node label="Play" hotkey="X" onClick={props.play} />
|
||||
|
|
@ -55,15 +58,17 @@ const PlaybackContextMenu = props => (
|
|||
</React.Fragment>
|
||||
);
|
||||
|
||||
const mapDispatchToProps = {
|
||||
previous,
|
||||
play,
|
||||
pause,
|
||||
stop,
|
||||
next,
|
||||
seekForward,
|
||||
seekBackward,
|
||||
nextN
|
||||
const mapDispatchToProps = (dispatch: Dispatch): Props => {
|
||||
return {
|
||||
previous: () => dispatch(Actions.previous()),
|
||||
play: () => dispatch(Actions.play()),
|
||||
pause: () => dispatch(Actions.pause()),
|
||||
stop: () => dispatch(Actions.stop()),
|
||||
next: () => dispatch(Actions.next()),
|
||||
seekForward: steps => dispatch(Actions.seekForward(steps)),
|
||||
seekBackward: steps => dispatch(Actions.seekBackward(steps)),
|
||||
nextN: steps => dispatch(Actions.nextN(steps))
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import * as Actions from "../actionCreators";
|
||||
import { Hr, Node, Parent } from "./ContextMenu";
|
||||
|
||||
const SkinContextMenu = props => (
|
||||
<Parent label="Skins">
|
||||
<Node onClick={props.openSkinFileDialog} label="Load Skin..." />
|
||||
<Hr />
|
||||
<Node onClick={props.loadDefaultSkin} label={"<Base Skin>"} />
|
||||
{props.availableSkins.map(skin => (
|
||||
<Node
|
||||
key={skin.url}
|
||||
onClick={() => props.setSkin(skin.url)}
|
||||
label={skin.name}
|
||||
/>
|
||||
))}
|
||||
</Parent>
|
||||
);
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
availableSkins: state.settings.availableSkins
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
loadDefaultSkin: Actions.loadDefaultSkin,
|
||||
openSkinFileDialog: Actions.openSkinFileDialog,
|
||||
setSkin: Actions.setSkinFromUrl
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(SkinContextMenu);
|
||||
55
js/components/SkinsContextMenu.tsx
Normal file
55
js/components/SkinsContextMenu.tsx
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import * as Actions from "../actionCreators";
|
||||
import { Hr, Node, Parent } from "./ContextMenu";
|
||||
import { AppState, Skin, Dispatch } from "../types";
|
||||
|
||||
interface StateProps {
|
||||
availableSkins: Skin[];
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
loadDefaultSkin(): void;
|
||||
setSkin(url: string): void;
|
||||
openSkinFileDialog(): void;
|
||||
}
|
||||
|
||||
type Props = StateProps & DispatchProps;
|
||||
|
||||
const SkinContextMenu = (props: Props) => (
|
||||
<Parent label="Skins">
|
||||
<Node onClick={props.openSkinFileDialog} label="Load Skin..." />
|
||||
<Hr />
|
||||
<Node onClick={props.loadDefaultSkin} label={"<Base Skin>"} />
|
||||
{props.availableSkins.map(skin => (
|
||||
<Node
|
||||
key={skin.url}
|
||||
onClick={() => props.setSkin(skin.url)}
|
||||
label={skin.name}
|
||||
/>
|
||||
))}
|
||||
</Parent>
|
||||
);
|
||||
|
||||
const mapStateToProps = (state: AppState): StateProps => ({
|
||||
availableSkins: state.settings.availableSkins
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => {
|
||||
return {
|
||||
loadDefaultSkin() {
|
||||
dispatch(Actions.loadDefaultSkin());
|
||||
},
|
||||
openSkinFileDialog() {
|
||||
dispatch(Actions.openSkinFileDialog());
|
||||
},
|
||||
setSkin(url: string) {
|
||||
dispatch(Actions.setSkinFromUrl(url));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(SkinContextMenu);
|
||||
Loading…
Add table
Add a link
Reference in a new issue