From d61585c8e3c40f756eeeafdd12af6d736ced9763 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Sat, 9 Mar 2019 17:26:09 -0800 Subject: [PATCH] Allow user to reshow the song title in Milkdrop --- js/actionCreators/index.ts | 3 ++- js/actionCreators/milkdrop.ts | 7 ++++++- js/actionTypes.ts | 1 + js/components/MilkdropWindow/Visualizer.tsx | 22 ++++++++++++++++++++- js/components/MilkdropWindow/index.tsx | 13 +++++++++--- js/reducers/milkdrop.ts | 22 +++++++++++++++++++-- js/types.ts | 1 + 7 files changed, 61 insertions(+), 8 deletions(-) diff --git a/js/actionCreators/index.ts b/js/actionCreators/index.ts index 09525dcd..53ea5305 100644 --- a/js/actionCreators/index.ts +++ b/js/actionCreators/index.ts @@ -105,7 +105,8 @@ export { handlePresetDrop, loadPresets, toggleRandomizePresets, - togglePresetCycling + togglePresetCycling, + scheduleMilkdropMessage } from "./milkdrop"; import * as Selectors from "../selectors"; diff --git a/js/actionCreators/milkdrop.ts b/js/actionCreators/milkdrop.ts index bac2748a..1def54a9 100644 --- a/js/actionCreators/milkdrop.ts +++ b/js/actionCreators/milkdrop.ts @@ -6,7 +6,8 @@ import { TOGGLE_PRESET_OVERLAY, PRESET_REQUESTED, TOGGLE_RANDOMIZE_PRESETS, - TOGGLE_PRESET_CYCLING + TOGGLE_PRESET_CYCLING, + SCHEDULE_MILKDROP_MESSAGE } from "../actionTypes"; import * as Selectors from "../selectors"; import { @@ -201,3 +202,7 @@ export function toggleRandomizePresets(): Dispatchable { export function togglePresetCycling(): Dispatchable { return { type: TOGGLE_PRESET_CYCLING }; } + +export function scheduleMilkdropMessage(message: string): Dispatchable { + return { type: SCHEDULE_MILKDROP_MESSAGE, message }; +} diff --git a/js/actionTypes.ts b/js/actionTypes.ts index 3a82bbe8..44eb675f 100644 --- a/js/actionTypes.ts +++ b/js/actionTypes.ts @@ -85,3 +85,4 @@ export const TOGGLE_PRESET_OVERLAY = "TOGGLE_PRESET_OVERLAY"; export const PRESET_REQUESTED = "PRESET_REQUESTED"; export const TOGGLE_RANDOMIZE_PRESETS = "TOGGLE_RANDOMIZE_PRESETS"; export const TOGGLE_PRESET_CYCLING = "TOGGLE_PRESET_CYCLING"; +export const SCHEDULE_MILKDROP_MESSAGE = "SCHEDULE_MILKDROP_MESSAGE"; diff --git a/js/components/MilkdropWindow/Visualizer.tsx b/js/components/MilkdropWindow/Visualizer.tsx index f36a390e..081330ea 100644 --- a/js/components/MilkdropWindow/Visualizer.tsx +++ b/js/components/MilkdropWindow/Visualizer.tsx @@ -18,6 +18,10 @@ interface StateProps { trackTitle: string | null; currentPreset: any; transitionType: TransitionType; + message: { + text: string; + time: number; + } | null; } interface OwnProps { @@ -93,6 +97,21 @@ function Visualizer(props: Props) { visualizer.launchSongTitleAnim(props.trackTitle); }, [visualizer, props.trackTitle]); + const lastShownMessage = useRef(null); + + useEffect(() => { + if (visualizer == null || props.message == null) { + return; + } + if ( + lastShownMessage.current == null || + props.message.time > lastShownMessage.current + ) { + lastShownMessage.current = Date.now(); + visualizer.launchSongTitleAnim(props.message.text); + } + }, [visualizer, props.message]); + const shouldAnimate = props.playing && props.isEnabledVisualizer; // Kick off the animation loop @@ -134,7 +153,8 @@ const mapStateToProps = (state: AppState): StateProps => ({ butterchurn: Selectors.getButterchurn(state), trackTitle: Selectors.getCurrentTrackDisplayName(state), currentPreset: Selectors.getCurrentPreset(state), - transitionType: Selectors.getPresetTransitionType(state) + transitionType: Selectors.getPresetTransitionType(state), + message: state.milkdrop.message }); export default connect(mapStateToProps)(Visualizer); diff --git a/js/components/MilkdropWindow/index.tsx b/js/components/MilkdropWindow/index.tsx index 97bb6d39..e6b15821 100644 --- a/js/components/MilkdropWindow/index.tsx +++ b/js/components/MilkdropWindow/index.tsx @@ -22,6 +22,7 @@ interface StateProps { desktop: boolean; overlay: boolean; presetsAreCycling: boolean; + trackTitle: string | null; } interface DispatchProps { @@ -34,6 +35,7 @@ interface DispatchProps { handlePresetDrop(e: React.DragEvent): void; selectNextPreset(transitionType?: TransitionType): void; selectPreviousPreset(transitionType?: TransitionType): void; + scheduleMilkdropMessage(message: string): void; } interface OwnProps { @@ -68,7 +70,9 @@ function Milkdrop(props: Props) { e.stopPropagation(); break; case 84: // T - // this.visualizer.launchSongTitleAnim(this.props.trackTitle); + if (props.trackTitle != null) { + props.scheduleMilkdropMessage(props.trackTitle); + } e.stopPropagation(); break; case 145: // scroll lock @@ -138,7 +142,8 @@ function Milkdrop(props: Props) { const mapStateToProps = (state: AppState): StateProps => ({ desktop: Selectors.getMilkdropDesktopEnabled(state), overlay: Selectors.getPresetOverlayOpen(state), - presetsAreCycling: Selectors.getPresetsAreCycling(state) + presetsAreCycling: Selectors.getPresetsAreCycling(state), + trackTitle: Selectors.getCurrentTrackDisplayName(state) }); const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({ @@ -152,7 +157,9 @@ const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({ selectNextPreset: (transitionType?: TransitionType) => dispatch(Actions.selectNextPreset(transitionType)), selectPreviousPreset: (transitionType?: TransitionType) => - dispatch(Actions.selectPreviousPreset(transitionType)) + dispatch(Actions.selectPreviousPreset(transitionType)), + scheduleMilkdropMessage: (message: string) => + dispatch(Actions.scheduleMilkdropMessage(message)) }); export default connect( diff --git a/js/reducers/milkdrop.ts b/js/reducers/milkdrop.ts index af0c7c78..78f9b2e1 100644 --- a/js/reducers/milkdrop.ts +++ b/js/reducers/milkdrop.ts @@ -8,11 +8,17 @@ import { TOGGLE_PRESET_OVERLAY, PRESET_REQUESTED, TOGGLE_RANDOMIZE_PRESETS, - TOGGLE_PRESET_CYCLING + TOGGLE_PRESET_CYCLING, + SCHEDULE_MILKDROP_MESSAGE } from "../actionTypes"; import * as Utils from "../utils"; import { TransitionType } from "../types"; +interface Message { + text: string; + time: number; +} + export interface MilkdropState { desktop: boolean; overlay: boolean; @@ -23,6 +29,9 @@ export interface MilkdropState { transitionType: TransitionType; randomize: boolean; cycling: boolean; + // TODO: This could probably be simplified to just a date and we could assume + // the song title is the message. + message: Message | null; } const defaultMilkdropState = { @@ -34,7 +43,8 @@ const defaultMilkdropState = { butterchurn: null, transitionType: TransitionType.DEFAULT, randomize: true, - cycling: true + cycling: true, + message: null }; export const milkdrop = ( @@ -84,6 +94,14 @@ export const milkdrop = ( return { ...state, randomize: !state.randomize }; case TOGGLE_PRESET_CYCLING: return { ...state, cycling: !state.cycling }; + case SCHEDULE_MILKDROP_MESSAGE: + return { + ...state, + message: { + text: action.message, + time: Date.now() + } + }; default: return state; } diff --git a/js/types.ts b/js/types.ts index 939611f2..46629658 100644 --- a/js/types.ts +++ b/js/types.ts @@ -462,6 +462,7 @@ export type Action = | { type: "LOAD_DEFAULT_SKIN" } | { type: "ENABLE_MEDIA_LIBRARY" } | { type: "ENABLE_MILKDROP"; open: boolean } + | { type: "SCHEDULE_MILKDROP_MESSAGE"; message: string } | { type: "SET_MILKDROP_DESKTOP"; enabled: boolean;