diff --git a/frontend/src/Call/CallPlayer.js b/frontend/src/Call/CallPlayer.js index 0038eaa..4972cdf 100644 --- a/frontend/src/Call/CallPlayer.js +++ b/frontend/src/Call/CallPlayer.js @@ -43,11 +43,12 @@ function CallPlayer(props) { threshold: 0.5 }); + const backgroundAutoplay = useSelector((state) => state.callPlayer.backgroundAutoplay); const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(shortName); const [autoPlay, setAutoPlay] = useState(true); const [currentCall, setCurrentCall] = useState(false); const [isPlaying, setIsPlaying] = useState(false); - + const [silenceCount, setSilenceCount] = useState(0); const { callLink, callDownload, callTweet } = useCallLink(currentCall) const dispatch = useDispatch(); @@ -76,16 +77,27 @@ function CallPlayer(props) { setIsPlaying(true); } + + /* This function gets called whenever the currently playing call ends.*/ + const callEnded = () => { if (callsData) { const currentIndex = callsData.ids.findIndex(callId => callId === currentCallId); - if (autoPlay && (currentIndex > 0)) { - const nextCallId = callsData.ids[currentIndex - 1]; - const nextCall = callsData.entities[nextCallId]; - console.log("Autoplaying next call, current Index is: " + currentIndex + " isPlaying is: " + isPlaying ) - setCurrentCall(nextCall); - dispatch(playedCall(nextCall._id)); - setIsPlaying(true); + if (autoPlay) { + if (currentIndex > 0) { + const nextCallId = callsData.ids[currentIndex - 1]; + const nextCall = callsData.entities[nextCallId]; + console.log("Autoplaying next call, current Index is: " + currentIndex + " isPlaying is: " + isPlaying ) + setCurrentCall(nextCall); + dispatch(playedCall(nextCall._id)); + setIsPlaying(true); + } else if (backgroundAutoplay) { + // there are no more calls to play, but we want to keep playing something so the webpage is not put to sleep, so we play silence! + setSilenceCount(silenceCount+1); + } else { + // there are no more calls to play and backgroundAutoplay is disabled + setIsPlaying(false); + } } else { if (!autoPlay) { console.log("Not playing because Autoplay is false - current index is: " + currentIndex) @@ -153,7 +165,7 @@ function CallPlayer(props) { handleAutoPlay(autoPlay)}>Autoplay - + Download diff --git a/frontend/src/Call/GroupModal.js b/frontend/src/Call/GroupModal.js deleted file mode 100644 index 22c23d2..0000000 --- a/frontend/src/Call/GroupModal.js +++ /dev/null @@ -1,146 +0,0 @@ -import React, { useState } from "react"; -import { useGetGroupsQuery } from '../features/api/apiSlice' -import { setGroupFilter } from "../features/callPlayer/callPlayerSlice"; -import { useSelector, useDispatch } from 'react-redux' - -import { - Modal, - Button, - Icon, - Dropdown -} from "semantic-ui-react"; -import "./FilterModal.css"; - -function GroupModal (props) { - const { data, isError, isLoading, isSuccess,error } = useGetGroupsQuery(props.shortName); - const [open, setOpen] = useState(false); - const [selectedGroup, setSelectedGroup] = useState(false); - const dispatch = useDispatch() - const onClose = props.onClose; - - function handleDone(onClose) { - - if (selectedGroup) { - dispatch(setGroupFilter(selectedGroup)) - //dispatch({type: types.SET_GROUP_FILTER, groupId: selectedGroup }) - onClose(true); - } else { - onClose(false); - } -} - - - let groupOptions = [] - - if (isSuccess) { - - for (const num in data) { - const group = data[num]; - var obj = { - key: group._id, - value: group._id, - text: group.groupName - } - groupOptions.push(obj); - } -} - - - return ( - - setOpen(false)} onOpen={() => setOpen(true)} size='tiny'> - - Select a Group - - -

Choose the type of calls you want to listen to

- setSelectedGroup(data.value)} /> - -
- -
- - - -
- - ) -} -/* -class GroupModal extends Component { - constructor(props) { - super(props) - this.handleInputChange = this.handleInputChange.bind(this); - this.handleDone = this.handleDone.bind(this); - this.handleClose = this.handleClose.bind(this); - - this.state = { - open: false, - selectedGroup: false - } -} - - -handleInputChange = (e, { name, value }) => this.setState({ [name]: value }); -handleClose = () => this.props.onClose(false); - -handleDone(event) { - - if (this.state.selectedGroup) { - this.props.callActions.setGroupFilter(this.state.selectedGroup); - this.props.onClose(true); - } else { - this.props.onClose(false); - } - -} -componentDidUpdate(prevProps) { - - const filterChanged = (prevProps.selectedGroup !== this.props.selectedGroup); - if (filterChanged) { - this.setState({ selectedGroup: this.props.selectedGroup}); - } -} - - render() { - - - var groupList = []; - if (this.props.groups) { - for (const num in this.props.groups) { - const group = this.props.groups[num]; - var obj = { - key: group._id, - value: group._id, - text: group.groupName - } - groupList.push(obj); - } - } - - return ( - - - Select a Group - - -

Choose the type of calls you want to listen to

- - -
- -
- - - -
- - ) - } -}*/ - -export default GroupModal; diff --git a/frontend/src/Call/components/GroupModal.js b/frontend/src/Call/components/GroupModal.js index e0ca925..da70d4b 100644 --- a/frontend/src/Call/components/GroupModal.js +++ b/frontend/src/Call/components/GroupModal.js @@ -1,6 +1,6 @@ import React, { Component, useState, useEffect } from "react"; import { useGetGroupsQuery, useGetSystemsQuery, } from '../../features/api/apiSlice' -import { setGroupFilter, setCenterCall } from "../../features/callPlayer/callPlayerSlice"; +import { setGroupFilter, setCenterCall, setBackgroundAutoplay } from "../../features/callPlayer/callPlayerSlice"; import { useSelector, useDispatch } from 'react-redux' import { @@ -15,11 +15,14 @@ import "./FilterModal.css"; function GroupModal(props) { const shortName = useSelector((state) => state.callPlayer.shortName); + const backgroundAutoplay = useSelector((state) => state.callPlayer.backgroundAutoplay); + const centerCall = useSelector((state) => state.callPlayer.centerCall); const { data: groupData, isSuccess } = useGetGroupsQuery(props.shortName); const { data: allSystems } = useGetSystemsQuery(); const [selectedGroup, setSelectedGroup] = useState(false); const [groupOptions, setGroupOptions] = useState([]); - const [centerCall, setLocalCenterCall] = useState(true); + const [localCenterCall, setLocalCenterCall] = useState(centerCall); + const [localBackgroundAutoplay, setLocalBackgroundAutoplay] = useState(backgroundAutoplay); const dispatch = useDispatch() const onClose = props.onClose; let system = false; @@ -30,7 +33,8 @@ function GroupModal(props) { } function handleDone(onClose) { - dispatch(setCenterCall(centerCall)); + dispatch(setCenterCall(localCenterCall)); + dispatch(setBackgroundAutoplay(localBackgroundAutoplay)); if (selectedGroup && (selectedGroup!="all")) { dispatch(setGroupFilter(selectedGroup)) @@ -83,7 +87,8 @@ function GroupModal(props) {

Choose the type of calls you want to listen to

setSelectedGroup(data.value)} /> - setLocalCenterCall(data.value)} /> + setLocalCenterCall(data.checked)} /> + setLocalBackgroundAutoplay(data.checked)} /> diff --git a/frontend/src/Call/components/MediaPlayer.js b/frontend/src/Call/components/MediaPlayer.js index 86df7fe..0c16882 100644 --- a/frontend/src/Call/components/MediaPlayer.js +++ b/frontend/src/Call/components/MediaPlayer.js @@ -17,6 +17,7 @@ const MediaPlayer = (props) => { const [playTime, setPlayTime] = useState(0); const [isPlaying, setIsPlaying] = useState(false); const parentHandlePlayPause = props.onPlayPause + const playSilence = props.playSilence; const handlePause = () => { setIsPlaying(false); } const handlePlay = () => { setIsPlaying(true); } @@ -61,6 +62,38 @@ const MediaPlayer = (props) => { } }, [call]); + useEffect(() => { + const audio = audioRef.current.audioEl.current; + + setSourceIndex(0); + navigator.mediaSession.metadata = new MediaMetadata({ + title: "Waiting for Call...", + album: 'OpenMHz', + artwork: [ + { src: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' }, + { src: '/android-chrome-192x192.png', sizes: '192x192', type: 'image/png' }, + { src: '/android-chrome-192x192.png', sizes: '512x512', type: 'image/png' }, + ] + }); + audio.src = "data:audio/mpeg;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4Ljc2LjEwMAAAAAAAAAAAAAAA/+M4wAAAAAAAAAAAAEluZm8AAAAPAAAAAwAAAbAAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV////////////////////////////////////////////AAAAAExhdmM1OC4xMwAAAAAAAAAAAAAAACQDkAAAAAAAAAGw9wrNaQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+MYxAAAAANIAAAAAExBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxDsAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxHYAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV"; + const playPromise = audio.play(); + + // In browsers that don’t yet support this functionality, + // playPromise won’t be defined. + if (playPromise !== undefined) { + playPromise.then(function () { + + }).catch(function (error) { + console.log("Automatic playback failed: " + error); + // Show a UI element to let the user manually start playback. + }); + } else { + audio.src = false; + } + + }, [playSilence]); + + const updatePlayProgress = () => { const audio = audioRef.current.audioEl.current; const { currentTime, duration } = audio; diff --git a/frontend/src/features/callPlayer/callPlayerSlice.js b/frontend/src/features/callPlayer/callPlayerSlice.js index 9a5bb18..1ee1329 100644 --- a/frontend/src/features/callPlayer/callPlayerSlice.js +++ b/frontend/src/features/callPlayer/callPlayerSlice.js @@ -15,7 +15,8 @@ const initialState = { currentCallId: false, playlist: [], live: false, - centerCall: true + centerCall: true, + backgroundAutoplay: false } const compareCalls = (a, b) => { @@ -77,6 +78,9 @@ export const callPlayerSlice = createSlice({ setCenterCall: (state,action) => { state.centerCall = action.payload; }, + setBackgroundAutoplay: (state,action) => { + state.backgroundAutoplay = action.payload; + }, setShortName: (state, action) => { state.shortName = action.payload; }, @@ -106,7 +110,7 @@ export const callPlayerSlice = createSlice({ }) // Action creators are generated for each case reducer function -export const { setCurrentCallId, setCallTime, setFilter, setLive, setCenterCall, setPlaylist, removeFromPLaylist, addToPlaylist, setShortName, setDateFilter, setStarredFilter, setAllFilter, setGroupFilter, setTalkgroupFilter } = callPlayerSlice.actions +export const { setCurrentCallId, setCallTime, setFilter, setLive, setCenterCall, setBackgroundAutoplay, setPlaylist, removeFromPLaylist, addToPlaylist, setShortName, setDateFilter, setStarredFilter, setAllFilter, setGroupFilter, setTalkgroupFilter } = callPlayerSlice.actions export default callPlayerSlice.reducer