From 4c0850b32e2448cc03d63848c530256242b7d270 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Fri, 18 Sep 2020 18:14:47 +0100 Subject: [PATCH 1/7] Unfinished attempt trying to add played state --- src/api.ts | 1 + src/mixer/state.ts | 9 ++++++++- src/showplanner/index.tsx | 7 +++++++ src/showplanner/state.ts | 12 ++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/api.ts b/src/api.ts index 70de072..5bb8489 100644 --- a/src/api.ts +++ b/src/api.ts @@ -85,6 +85,7 @@ interface TimeslotItemBase { length: string; trackid: number; clean: boolean; + played: boolean; } interface TimeslotItemCentral { diff --git a/src/mixer/state.ts b/src/mixer/state.ts index 8a0ca15..73980ba 100644 --- a/src/mixer/state.ts +++ b/src/mixer/state.ts @@ -6,7 +6,7 @@ import { } from "@reduxjs/toolkit"; import fetchProgress, { FetchProgressData } from "fetch-progress"; import Between from "between.js"; -import { itemId, PlanItem } from "../showplanner/state"; +import { itemId, PlanItem, setItemPlayed } from "../showplanner/state"; import * as BroadcastState from "../broadcast/state"; import Keys from "keymaster"; import { Track, MYRADIO_NON_API_BASE, AuxItem } from "../api"; @@ -14,6 +14,7 @@ import { AppThunk } from "../store"; import { RootState } from "../rootReducer"; import { audioEngine } from "./audio"; import * as TheNews from "./the_news"; +import Showplanner from "../showplanner"; const playerGainTweens: Array<{ target: VolumePresetEnum; @@ -359,7 +360,13 @@ export const load = ( }); playerInstance.on("play", () => { + dispatch(mixerState.actions.setPlayerState({ player, state: "playing" })); + + const state = getState().mixer.players[player]; + if (state.loadedItem != null) { + dispatch(setItemPlayed(state.loadedItem.id, true)); + } }); playerInstance.on("pause", () => { dispatch( diff --git a/src/showplanner/index.tsx b/src/showplanner/index.tsx index bacb975..7ba6804 100644 --- a/src/showplanner/index.tsx +++ b/src/showplanner/index.tsx @@ -23,6 +23,7 @@ import { moveItem, addItem, removeItem, + setItemPlayed, getPlaylists, } from "./state"; @@ -241,6 +242,7 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) { timeslotitemid: "I" + insertIndex, channel: parseInt(result.destination.droppableId, 10), weight: result.destination.index, + played: false, ...data, }; dispatch(addItem(timeslotId, newItem)); @@ -255,6 +257,7 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) { channel: parseInt(result.destination.droppableId, 10), weight: result.destination.index, clean: true, + played: false, ...data, } as any; dispatch(addItem(timeslotId, newItem)); @@ -273,6 +276,9 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) { async function onCtxRemoveClick(e: any, data: { id: string }) { dispatch(removeItem(timeslotId, data.id)); } + async function onCtxUnPlayedClick(e: any, data: { id: string }) { + dispatch(setItemPlayed(data.id, false)); + } if (showplan === null) { return ( @@ -319,6 +325,7 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) { Remove + Mark Unplayed async (dispatch, getState) => { + const plan = cloneDeep(getState().showplan.plan!); + const item = plan.find((x) => itemId(x) === itemid)!; + item.played = played; +}; + export const getShowplan = (timeslotId: number): AppThunk => async ( dispatch ) => { From 1ef555e312aa2f18acc93f6387a56e6e7327fa33 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 00:20:11 +0000 Subject: [PATCH 2/7] Actually fix plan state to store played status. --- src/api.ts | 1 - src/mixer/state.ts | 4 +++- src/showplanner/Item.tsx | 1 + src/showplanner/index.tsx | 7 ++++--- src/showplanner/state.ts | 32 +++++++++++++++++++------------- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/api.ts b/src/api.ts index ef06b76..f66a941 100644 --- a/src/api.ts +++ b/src/api.ts @@ -86,7 +86,6 @@ interface TimeslotItemBase { trackid: number; clean: boolean; cue: number; - played: boolean; } interface TimeslotItemCentral { diff --git a/src/mixer/state.ts b/src/mixer/state.ts index 696f675..588598f 100644 --- a/src/mixer/state.ts +++ b/src/mixer/state.ts @@ -451,7 +451,9 @@ export const load = ( const state = getState().mixer.players[player]; if (state.loadedItem != null) { - dispatch(setItemPlayed(state.loadedItem.id, true)); + dispatch( + setItemPlayed({ itemId: itemId(state.loadedItem), played: true }) + ); } }); playerInstance.on("pause", () => { diff --git a/src/showplanner/Item.tsx b/src/showplanner/Item.tsx index 7226b27..c0242ba 100644 --- a/src/showplanner/Item.tsx +++ b/src/showplanner/Item.tsx @@ -57,6 +57,7 @@ export const Item = memo(function Item({ data-itemid={id} className={ "item " + + ("played" in x ? (x.played ? "played " : "") : "") + x.type + `${ column >= 0 && diff --git a/src/showplanner/index.tsx b/src/showplanner/index.tsx index 0853199..5be7371 100644 --- a/src/showplanner/index.tsx +++ b/src/showplanner/index.tsx @@ -33,6 +33,7 @@ import { removeItem, setItemPlayed, getPlaylists, + PlanItemBase, } from "./state"; import * as MixerState from "../mixer/state"; @@ -334,7 +335,7 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) { // this is a track from the CML // TODO: this is ugly, should be in redux const data = CML_CACHE[result.draggableId]; - const newItem: TimeslotItem = { + const newItem: TimeslotItem & PlanItemBase = { timeslotitemid: "I" + insertIndex, channel: parseInt(result.destination.droppableId, 10), weight: result.destination.index, @@ -348,7 +349,7 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) { // this is an aux resource // TODO: this is ugly, should be in redux const data = AUX_CACHE[result.draggableId]; - const newItem: TimeslotItem = { + const newItem: TimeslotItem & PlanItemBase = { timeslotitemid: "I" + insertIndex, channel: parseInt(result.destination.droppableId, 10), weight: result.destination.index, @@ -381,7 +382,7 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) { dispatch(removeItem(timeslotId, data.id)); } async function onCtxUnPlayedClick(e: any, data: { id: string }) { - dispatch(setItemPlayed(data.id, false)); + dispatch(setItemPlayed({ itemId: data.id, played: false })); } // Add support for reloading the show plan from the iFrames. diff --git a/src/showplanner/state.ts b/src/showplanner/state.ts index 858f6ee..081cd8e 100644 --- a/src/showplanner/state.ts +++ b/src/showplanner/state.ts @@ -17,10 +17,12 @@ export interface ItemGhost { cue: number; outro: number; clean: boolean; - played: boolean; } -export type PlanItem = TimeslotItem | ItemGhost; +export interface PlanItemBase { + played?: boolean; +} +export type PlanItem = (TimeslotItem | ItemGhost) & PlanItemBase; export type Plan = PlanItem[][]; @@ -175,6 +177,16 @@ const showplan = createSlice({ } }); }, + // Set the item as being played/unplayed in this session. + setItemPlayed( + state, + action: PayloadAction<{ itemId: string; played: boolean }> + ) { + const idx = state.plan!.findIndex( + (x) => itemId(x) === action.payload.itemId + ); + state.plan![idx].played = action.payload.played; + }, replaceGhost( state, action: PayloadAction<{ ghostId: string; newItemData: TimeslotItem }> @@ -201,7 +213,11 @@ const showplan = createSlice({ export default showplan.reducer; -export const { setItemTimings, planSaveError } = showplan.actions; +export const { + setItemTimings, + setItemPlayed, + planSaveError, +} = showplan.actions; export const moveItem = ( timeslotid: number, @@ -480,16 +496,6 @@ export const removeItem = ( dispatch(showplan.actions.setPlanSaving(false)); }; -// Set the item as being played/unplayed in this session. -export const setItemPlayed = ( - itemid: string, - played: boolean -): AppThunk => async (dispatch, getState) => { - const plan = cloneDeep(getState().showplan.plan!); - const item = plan.find((x) => itemId(x) === itemid)!; - item.played = played; -}; - export const getShowplan = (timeslotId: number): AppThunk => async ( dispatch ) => { From d5f52ddcbe68bab3c55e512cfdcc54090b546956 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 00:21:49 +0000 Subject: [PATCH 3/7] Make icon show played items. --- src/showplanner/item.scss | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/showplanner/item.scss b/src/showplanner/item.scss index 8c40bba..dd4a409 100644 --- a/src/showplanner/item.scss +++ b/src/showplanner/item.scss @@ -15,11 +15,15 @@ opacity: 0.5; } + &.played .icon { + border: 4px black solid; + } + .icon { margin: auto auto; - margin-top: 2px; - height: 16px; - width: 16px; + margin-bottom: -3px; + height: 18px; + width: 18px; display: inline-block; border-radius: 50%; From 5c4b2b70ccb5aba3426045e5f43632886f7eae44 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 00:34:45 +0000 Subject: [PATCH 4/7] Allow going LIVE and nav bar to reset played indicators. --- src/broadcast/state.ts | 3 +++ src/navbar/index.tsx | 11 ++++++++++- src/showplanner/index.tsx | 5 ++++- src/showplanner/state.ts | 7 +++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/broadcast/state.ts b/src/broadcast/state.ts index ed86b3c..e4a94ac 100644 --- a/src/broadcast/state.ts +++ b/src/broadcast/state.ts @@ -7,6 +7,7 @@ import * as NavbarState from "../navbar/state"; import { ConnectionStateEnum } from "./streamer"; import { RecordingStreamer } from "./recording_streamer"; import { audioEngine } from "../mixer/audio"; +import { setItemPlayed } from "../showplanner/state"; export let streamer: WebRTCStreamer | null = null; @@ -315,6 +316,8 @@ export const goOnAir = (): AppThunk => async (dispatch, getState) => { } else if (state === "CONNECTED") { // okay, we've connected dispatch(registerForShow()); + } else if (state === "LIVE") { + dispatch(setItemPlayed({ itemId: "all", played: false })); } }); await streamer.start(); diff --git a/src/navbar/index.tsx b/src/navbar/index.tsx index 8c71239..3348aa8 100644 --- a/src/navbar/index.tsx +++ b/src/navbar/index.tsx @@ -23,7 +23,7 @@ import "./navbar.scss"; import { closeAlert } from "./state"; import { ConnectionStateEnum } from "../broadcast/streamer"; import { VUMeter } from "../optionsMenu/helpers/VUMeter"; -import { getShowplan } from "../showplanner/state"; +import { getShowplan, setItemPlayed } from "../showplanner/state"; import * as OptionsMenuState from "../optionsMenu/state"; @@ -107,6 +107,15 @@ export function NavBarMyRadio() { > Reload Show Plan +
{sessionState.currentTimeslot?.title}
diff --git a/src/showplanner/index.tsx b/src/showplanner/index.tsx index 5be7371..e592ca8 100644 --- a/src/showplanner/index.tsx +++ b/src/showplanner/index.tsx @@ -8,6 +8,7 @@ import { FaMicrophone, FaTrash, FaUpload, + FaCircleNotch, } from "react-icons/fa"; import { VUMeter } from "../optionsMenu/helpers/VUMeter"; import Stopwatch from "react-stopwatch"; @@ -441,7 +442,9 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) { Remove - Mark Unplayed + + Mark Unplayed + ) { + // Used for the nav menu + if (action.payload.itemId === "all") { + state.plan!.forEach((x) => { + x.played = action.payload.played; + }); + return; + } const idx = state.plan!.findIndex( (x) => itemId(x) === action.payload.itemId ); From 202d8aa6d4e1ec802ae9165ec0150f513ef22e01 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 00:39:20 +0000 Subject: [PATCH 5/7] Add bg to played items to be more obvious. --- src/showplanner/item.scss | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/showplanner/item.scss b/src/showplanner/item.scss index dd4a409..76e714c 100644 --- a/src/showplanner/item.scss +++ b/src/showplanner/item.scss @@ -15,8 +15,11 @@ opacity: 0.5; } - &.played .icon { - border: 4px black solid; + &.played { + background-color: #ddd; + .icon { + border: 4px black solid; + } } .icon { From 22ae79d70596af42345190e472b8702d1183111e Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 00:41:26 +0000 Subject: [PATCH 6/7] Remove unused import --- src/mixer/state.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mixer/state.ts b/src/mixer/state.ts index 588598f..9c4cf08 100644 --- a/src/mixer/state.ts +++ b/src/mixer/state.ts @@ -14,7 +14,6 @@ import { AppThunk } from "../store"; import { RootState } from "../rootReducer"; import { audioEngine } from "./audio"; import * as TheNews from "./the_news"; -import Showplanner from "../showplanner"; const playerGainTweens: Array<{ target: VolumePresetEnum; From eca3895537c6cfa4cbee57af619a20bab7cfbd19 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 00:44:31 +0000 Subject: [PATCH 7/7] Remove unused raygun import. --- src/store.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/store.ts b/src/store.ts index 18274d6..517b189 100644 --- a/src/store.ts +++ b/src/store.ts @@ -1,4 +1,3 @@ -import raygun from "raygun4js"; import { configureStore, Action,