mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-22 09:37:17 +00:00
194 lines
4.9 KiB
TypeScript
194 lines
4.9 KiB
TypeScript
import React from "react";
|
|
import { connect } from "react-redux";
|
|
import classnames from "classnames";
|
|
import { WINDOWS, MEDIA_STATUS, LOAD_STYLE } from "../../constants";
|
|
import * as Actions from "../../actionCreators";
|
|
import { getWindowShade } from "../../selectors";
|
|
|
|
import DropTarget from "../DropTarget";
|
|
import MiniTime from "../MiniTime";
|
|
|
|
import ClickedDiv from "../ClickedDiv";
|
|
import ContextMenuTarget from "../ContextMenuTarget";
|
|
import Visualizer from "../Visualizer";
|
|
import ActionButtons from "./ActionButtons";
|
|
import MainBalance from "./MainBalance";
|
|
import Close from "./Close";
|
|
import ClutterBar from "./ClutterBar";
|
|
import MainContextMenu from "./MainContextMenu";
|
|
import Eject from "./Eject";
|
|
import EqToggleButton from "./EqToggleButton";
|
|
import PlaylistToggleButton from "./PlaylistToggleButton";
|
|
import Kbps from "./Kbps";
|
|
import Khz from "./Khz";
|
|
import Marquee from "./Marquee";
|
|
import MonoStereo from "./MonoStereo";
|
|
import Position from "./Position";
|
|
import Repeat from "./Repeat";
|
|
import Shade from "./Shade";
|
|
import Minimize from "./Minimize";
|
|
import Shuffle from "./Shuffle";
|
|
import Time from "./Time";
|
|
import MainVolume from "./MainVolume";
|
|
|
|
import "../../../css/main-window.css";
|
|
import {
|
|
MediaStatus,
|
|
WindowId,
|
|
AppState,
|
|
Dispatch,
|
|
FilePicker,
|
|
} from "../../types";
|
|
import FocusTarget from "../FocusTarget";
|
|
|
|
interface StateProps {
|
|
focused: WindowId | null;
|
|
loading: boolean;
|
|
doubled: boolean;
|
|
mainShade: boolean;
|
|
llama: boolean;
|
|
working: boolean;
|
|
status: MediaStatus | null;
|
|
}
|
|
|
|
interface DispatchProps {
|
|
scrollVolume(e: React.WheelEvent<HTMLDivElement>): void;
|
|
toggleMainWindowShadeMode(): void;
|
|
loadMedia(e: React.DragEvent<HTMLDivElement>): void;
|
|
}
|
|
|
|
interface OwnProps {
|
|
analyser: AnalyserNode;
|
|
filePickers: FilePicker[];
|
|
}
|
|
|
|
type Props = StateProps & DispatchProps & OwnProps;
|
|
|
|
const MainWindow = (props: Props) => {
|
|
const {
|
|
focused,
|
|
loading,
|
|
doubled,
|
|
mainShade,
|
|
llama,
|
|
status,
|
|
working,
|
|
filePickers,
|
|
} = props;
|
|
|
|
const className = classnames({
|
|
window: true,
|
|
play: status === MEDIA_STATUS.PLAYING,
|
|
stop: status === MEDIA_STATUS.STOPPED,
|
|
pause: status === MEDIA_STATUS.PAUSED,
|
|
selected: focused === WINDOWS.MAIN,
|
|
shade: mainShade,
|
|
draggable: true,
|
|
loading,
|
|
doubled,
|
|
llama,
|
|
});
|
|
|
|
return (
|
|
<React.StrictMode>
|
|
<DropTarget
|
|
id="main-window"
|
|
className={className}
|
|
handleDrop={props.loadMedia}
|
|
onWheel={props.scrollVolume}
|
|
>
|
|
<FocusTarget windowId={WINDOWS.MAIN}>
|
|
<div
|
|
id="title-bar"
|
|
className="selected draggable"
|
|
onDoubleClick={props.toggleMainWindowShadeMode}
|
|
>
|
|
<ContextMenuTarget
|
|
id="option-context"
|
|
bottom
|
|
handle={<ClickedDiv id="option" title="Winamp Menu" />}
|
|
>
|
|
<MainContextMenu filePickers={filePickers} />
|
|
</ContextMenuTarget>
|
|
{mainShade && <MiniTime />}
|
|
<Minimize />
|
|
<Shade />
|
|
<Close />
|
|
</div>
|
|
<div className="status">
|
|
<ClutterBar />
|
|
{!working && <div id="play-pause" />}
|
|
<div
|
|
id="work-indicator"
|
|
className={classnames({ selected: working })}
|
|
/>
|
|
<Time />
|
|
</div>
|
|
<Visualizer
|
|
// @ts-ignore Visualizer is not typed yet
|
|
analyser={props.analyser}
|
|
/>
|
|
<div className="media-info">
|
|
<Marquee />
|
|
<Kbps />
|
|
<Khz />
|
|
<MonoStereo />
|
|
</div>
|
|
<MainVolume />
|
|
<MainBalance />
|
|
<div className="windows">
|
|
<EqToggleButton />
|
|
<PlaylistToggleButton />
|
|
</div>
|
|
<Position />
|
|
<ActionButtons />
|
|
<Eject />
|
|
<div className="shuffle-repeat">
|
|
<Shuffle />
|
|
<Repeat />
|
|
</div>
|
|
<a
|
|
id="about"
|
|
target="_blank"
|
|
href="https://webamp.org/about"
|
|
title="About"
|
|
/>
|
|
</FocusTarget>
|
|
</DropTarget>
|
|
</React.StrictMode>
|
|
);
|
|
};
|
|
|
|
const mapStateToProps = (state: AppState): StateProps => {
|
|
const {
|
|
media: { status },
|
|
display: { loading, doubled, llama, working },
|
|
windows: { focused },
|
|
} = state;
|
|
return {
|
|
mainShade: Boolean(getWindowShade(state)("main")),
|
|
status,
|
|
loading,
|
|
doubled,
|
|
llama,
|
|
working,
|
|
focused,
|
|
};
|
|
};
|
|
|
|
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => {
|
|
return {
|
|
toggleMainWindowShadeMode: () =>
|
|
dispatch(Actions.toggleMainWindowShadeMode()),
|
|
scrollVolume: (e: React.WheelEvent<HTMLDivElement>) =>
|
|
dispatch(Actions.scrollVolume(e)),
|
|
loadMedia: (e: React.DragEvent<HTMLDivElement>) =>
|
|
dispatch(Actions.loadMedia(e, LOAD_STYLE.PLAY)),
|
|
};
|
|
};
|
|
export default connect(
|
|
mapStateToProps,
|
|
mapDispatchToProps,
|
|
null,
|
|
{ forwardRef: true }
|
|
)(MainWindow);
|