diff --git a/src/App.css b/src/App.css index a36a337..68e0cfa 100644 --- a/src/App.css +++ b/src/App.css @@ -99,20 +99,42 @@ button { flex: 1; font-size: 0.8em; } +.timing-buttons .delete { + max-width: 3em; + color: gray; + padding-bottom: 2px; +} .timing-buttons .intro { - border-color: rgba(125, 0, 255, 0.8); - color: rgba(125, 0, 255, 0.8); + border-color: rgb(125, 0, 255); + color: rgb(125, 0, 255); } .timing-buttons .cue { - border-color: rgba(0, 100, 0, 0.9); - color: rgba(0, 100, 0, 0.9); + border-color: rgb(0, 100, 0); + color: rgb(0, 100, 0); } .timing-buttons .outro { - border-color: rgba(255, 0, 0, 0.7); - color: rgba(255, 0, 0, 0.7); + border-color: rgb(255, 0, 0); + color: rgb(255, 0, 0); +} + +.timing-buttons.not-central .intro, +.timing-buttons.not-central .outro { + opacity: 0.2; +} + +.timing-buttons.text-light > * { + color: white; +} + +.timing-buttons.text-light .intro { + border-color: rgb(179, 115, 248); +} + +.timing-buttons.text-light .cue { + border-color: rgb(0, 255, 0); } .waveform span { diff --git a/src/App.scss b/src/App.scss index d1adc63..20c33c6 100644 --- a/src/App.scss +++ b/src/App.scss @@ -76,6 +76,8 @@ $number-of-channels: 3; background: black; canvas { max-width: 100%; + border-left: 1px solid gray; + border-right: 1px solid gray; } } } @@ -99,7 +101,13 @@ $number-of-channels: 3; } .mic-control { background: var(--sidebar-background); - padding: 0 0 0.4rem 0; + position: relative; + .toggle { + cursor: pointer; + position: absolute; + right: 1em; + top: 0.2em; + } } } #sidebar-toggle { @@ -127,6 +135,12 @@ $number-of-channels: 3; box-sizing: content-box; } +#importerIframe { + width: 100%; + height: 100%; + box-sizing: content-box; +} + .sp-mic-live { position: fixed; top: 0; diff --git a/src/mixer/audio.ts b/src/mixer/audio.ts index 1f6fcd6..37bbbe2 100644 --- a/src/mixer/audio.ts +++ b/src/mixer/audio.ts @@ -102,7 +102,8 @@ class Player extends ((PlayerEmitter as unknown) as { new (): EventEmitter }) { if ("outro" in this.wavesurfer.regions.list) { // If the outro is set to 0, we assume that's no outro. if (startTime === 0) { - delete this.wavesurfer.regions.list.outro; + // Can't just delete the outro, so set it to the end of the track to hide it. + this.wavesurfer.regions.list.outro.start = this.wavesurfer.regions.list.outro.end; } else { this.wavesurfer.regions.list.outro.start = startTime; } diff --git a/src/navbar/index.tsx b/src/navbar/index.tsx index 8dca731..8c71239 100644 --- a/src/navbar/index.tsx +++ b/src/navbar/index.tsx @@ -10,6 +10,7 @@ import { FaBroadcastTower, FaSpinner, FaExclamationTriangle, + FaCog, } from "react-icons/fa"; import { RootState } from "../rootReducer"; @@ -24,6 +25,8 @@ import { ConnectionStateEnum } from "../broadcast/streamer"; import { VUMeter } from "../optionsMenu/helpers/VUMeter"; import { getShowplan } from "../showplanner/state"; +import * as OptionsMenuState from "../optionsMenu/state"; + function nicifyConnectionState(state: ConnectionStateEnum): string { switch (state) { case "CONNECTED": @@ -238,7 +241,7 @@ export function NavBarMain() { "btn rounded-0 pt-2 pb-1 nav-item nav-link " + (broadcastState.recordingState === "CONNECTED" ? "btn-outline-danger active" - : "btn-outline-warning") + : "btn-outline-light") } onClick={() => dispatch( @@ -270,6 +273,13 @@ export function NavBarMain() { )} )} +
  • dispatch(OptionsMenuState.open())} + > + Options +
  • +
  • { + window.addEventListener( + "message", + (event) => { + if (!event.origin.includes("ury.org.uk")) { + return; + } + if (event.data === "reload_showplan") { + props.close(); + } + }, + false + ); + }); return (
    @@ -28,8 +44,8 @@ export function ImporterModal(props: ImporterProps) {

    diff --git a/src/showplanner/LibraryUploadModal.tsx b/src/showplanner/LibraryUploadModal.tsx index 9f43faf..e989195 100644 --- a/src/showplanner/LibraryUploadModal.tsx +++ b/src/showplanner/LibraryUploadModal.tsx @@ -27,7 +27,9 @@ export function LibraryUploadModal(props: LibraryUploadProps) {
    diff --git a/src/showplanner/Player.tsx b/src/showplanner/Player.tsx index c70a4f7..d539d60 100644 --- a/src/showplanner/Player.tsx +++ b/src/showplanner/Player.tsx @@ -7,6 +7,7 @@ import { FaPlay, FaPause, FaStop, + FaTrash, } from "react-icons/fa"; import { omit } from "lodash"; import { RootState } from "../rootReducer"; @@ -64,10 +65,12 @@ const setTrackIntro = ( track: api.Track, secs: number, player: number -): AppThunk => async (dispatch) => { +): AppThunk => async (dispatch, getState) => { try { dispatch(MixerState.setLoadedItemIntro(player, secs)); - await api.setTrackIntro(track.trackid, secs); + if (getState().settings.saveShowPlanChanges) { + await api.setTrackIntro(track.trackid, secs); + } dispatch(ShowPlanState.setItemTimings({ item: track, intro: secs })); } catch (e) { dispatch(ShowPlanState.planSaveError("Failed saving track intro.")); @@ -79,10 +82,12 @@ const setTrackOutro = ( track: api.Track, secs: number, player: number -): AppThunk => async (dispatch) => { +): AppThunk => async (dispatch, getState) => { try { dispatch(MixerState.setLoadedItemOutro(player, secs)); - await api.setTrackOutro(track.trackid, secs); + if (getState().settings.saveShowPlanChanges) { + await api.setTrackOutro(track.trackid, secs); + } dispatch(ShowPlanState.setItemTimings({ item: track, outro: secs })); } catch (e) { dispatch(ShowPlanState.planSaveError("Failed saving track outro.")); @@ -94,10 +99,12 @@ const setTrackCue = ( item: api.TimeslotItem, secs: number, player: number -): AppThunk => async (dispatch) => { +): AppThunk => async (dispatch, getState) => { try { dispatch(MixerState.setLoadedItemCue(player, secs)); - await api.setTimeslotItemCue(item.timeslotitemid, secs); + if (getState().settings.saveShowPlanChanges) { + await api.setTimeslotItemCue(item.timeslotitemid, secs); + } dispatch(ShowPlanState.setItemTimings({ item, cue: secs })); } catch (e) { dispatch(ShowPlanState.planSaveError("Failed saving track cue.")); @@ -108,14 +115,30 @@ const setTrackCue = ( function TimingButtons({ id }: { id: number }) { const dispatch = useDispatch(); const state = useSelector((state: RootState) => state.mixer.players[id]); + const [showDeleteMenu, setShowDeleteMenu] = useState(false); + return ( -
    -
    Set Marker:
    +
    +
    {showDeleteMenu ? "Delete:" : "Set"} Marker:
    { if (state.loadedItem?.type === "central") { - dispatch(setTrackIntro(state.loadedItem, state.timeCurrent, id)); + dispatch( + setTrackIntro( + state.loadedItem, + showDeleteMenu ? 0 : state.timeCurrent, + id + ) + ); } }} > @@ -125,7 +148,13 @@ function TimingButtons({ id }: { id: number }) { className="cue btn btn-sm btn-outline-secondary rounded-0" onClick={() => { if (state.loadedItem && "timeslotitemid" in state.loadedItem) { - dispatch(setTrackCue(state.loadedItem, state.timeCurrent, id)); + dispatch( + setTrackCue( + state.loadedItem, + showDeleteMenu ? 0 : state.timeCurrent, + id + ) + ); } }} > @@ -135,12 +164,29 @@ function TimingButtons({ id }: { id: number }) { className="outro btn btn-sm btn-outline-secondary rounded-0" onClick={() => { if (state.loadedItem?.type === "central") { - dispatch(setTrackOutro(state.loadedItem, state.timeCurrent, id)); + dispatch( + setTrackOutro( + state.loadedItem, + showDeleteMenu ? 0 : state.timeCurrent, + id + ) + ); } }} > Outro
    +
    { + setShowDeleteMenu(!showDeleteMenu); + }} + > + +
    ); } diff --git a/src/showplanner/WelcomeModal.tsx b/src/showplanner/WelcomeModal.tsx index e25227c..96c7b91 100644 --- a/src/showplanner/WelcomeModal.tsx +++ b/src/showplanner/WelcomeModal.tsx @@ -1,5 +1,7 @@ import React from "react"; +import { FaTimes } from "react-icons/fa"; import Modal from "react-modal"; +import { Button } from "reactstrap"; interface WelcomeModalProps { isOpen: boolean; @@ -9,7 +11,15 @@ interface WelcomeModalProps { export function WelcomeModal(props: WelcomeModalProps) { return ( -

    Welcome to WebStudio!

    +

    Welcome to WebStudio!

    + +

    As you are not WebStudio Trained, you will be able to access all WebStudio features except going live. If you want to go live, ask in @@ -20,11 +30,6 @@ export function WelcomeModal(props: WelcomeModalProps) { Computing in #remote-broadcasting.

    Thank you, and have fun!

    -
    - -
    ); } diff --git a/src/showplanner/index.tsx b/src/showplanner/index.tsx index e4022bf..426c541 100644 --- a/src/showplanner/index.tsx +++ b/src/showplanner/index.tsx @@ -2,9 +2,9 @@ import React, { useState, useReducer, useEffect } from "react"; import { ContextMenu, MenuItem } from "react-contextmenu"; import { useBeforeunload } from "react-beforeunload"; import { - FaAlignJustify, FaBookOpen, FaFileImport, + FaBars, FaMicrophone, FaTrash, FaUpload, @@ -134,7 +134,7 @@ function LibraryColumn() {
    setTrack(e.target.value)} /> setTrack(e.target.value)} />