mirror of
https://github.com/openmhz/trunk-server.git
synced 2026-11-14 17:58:02 -05:00
background autoplaying
This commit is contained in:
@@ -43,11 +43,12 @@ function CallPlayer(props) {
|
|||||||
threshold: 0.5
|
threshold: 0.5
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const backgroundAutoplay = useSelector((state) => state.callPlayer.backgroundAutoplay);
|
||||||
const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(shortName);
|
const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(shortName);
|
||||||
const [autoPlay, setAutoPlay] = useState(true);
|
const [autoPlay, setAutoPlay] = useState(true);
|
||||||
const [currentCall, setCurrentCall] = useState(false);
|
const [currentCall, setCurrentCall] = useState(false);
|
||||||
const [isPlaying, setIsPlaying] = useState(false);
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
|
const [silenceCount, setSilenceCount] = useState(0);
|
||||||
const { callLink, callDownload, callTweet } = useCallLink(currentCall)
|
const { callLink, callDownload, callTweet } = useCallLink(currentCall)
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -76,16 +77,27 @@ function CallPlayer(props) {
|
|||||||
setIsPlaying(true);
|
setIsPlaying(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function gets called whenever the currently playing call ends.*/
|
||||||
|
|
||||||
const callEnded = () => {
|
const callEnded = () => {
|
||||||
if (callsData) {
|
if (callsData) {
|
||||||
const currentIndex = callsData.ids.findIndex(callId => callId === currentCallId);
|
const currentIndex = callsData.ids.findIndex(callId => callId === currentCallId);
|
||||||
if (autoPlay && (currentIndex > 0)) {
|
if (autoPlay) {
|
||||||
const nextCallId = callsData.ids[currentIndex - 1];
|
if (currentIndex > 0) {
|
||||||
const nextCall = callsData.entities[nextCallId];
|
const nextCallId = callsData.ids[currentIndex - 1];
|
||||||
console.log("Autoplaying next call, current Index is: " + currentIndex + " isPlaying is: " + isPlaying )
|
const nextCall = callsData.entities[nextCallId];
|
||||||
setCurrentCall(nextCall);
|
console.log("Autoplaying next call, current Index is: " + currentIndex + " isPlaying is: " + isPlaying )
|
||||||
dispatch(playedCall(nextCall._id));
|
setCurrentCall(nextCall);
|
||||||
setIsPlaying(true);
|
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 {
|
} else {
|
||||||
if (!autoPlay) {
|
if (!autoPlay) {
|
||||||
console.log("Not playing because Autoplay is false - current index is: " + currentIndex)
|
console.log("Not playing because Autoplay is false - current index is: " + currentIndex)
|
||||||
@@ -153,7 +165,7 @@ function CallPlayer(props) {
|
|||||||
|
|
||||||
<Menu fixed="bottom" compact inverted >
|
<Menu fixed="bottom" compact inverted >
|
||||||
<Menu.Item active={autoPlay} onClick={() => handleAutoPlay(autoPlay)}><Icon name="level up" /><span className="desktop-only">Autoplay</span></Menu.Item>
|
<Menu.Item active={autoPlay} onClick={() => handleAutoPlay(autoPlay)}><Icon name="level up" /><span className="desktop-only">Autoplay</span></Menu.Item>
|
||||||
<MediaPlayer call={currentCall} onEnded={callEnded} onPlayPause={handlePlayPause} />
|
<MediaPlayer call={currentCall} playSilence={silenceCount} onEnded={callEnded} onPlayPause={handlePlayPause} />
|
||||||
<Menu.Menu position="right" className="desktop-only">
|
<Menu.Menu position="right" className="desktop-only">
|
||||||
<Menu.Item><SupportModal /></Menu.Item>
|
<Menu.Item><SupportModal /></Menu.Item>
|
||||||
<Menu.Item><a href={callDownload}><Icon name="download" />Download</a></Menu.Item>
|
<Menu.Item><a href={callDownload}><Icon name="download" />Download</a></Menu.Item>
|
||||||
|
|||||||
@@ -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 (
|
|
||||||
|
|
||||||
<Modal open={props.open} onClose={() => setOpen(false)} onOpen={() => setOpen(true)} size='tiny'>
|
|
||||||
|
|
||||||
<Modal.Header>Select a Group</Modal.Header>
|
|
||||||
<Modal.Content >
|
|
||||||
<Modal.Description>
|
|
||||||
<p>Choose the type of calls you want to listen to</p>
|
|
||||||
<Dropdown placeholder='Group...' fluid selection options={groupOptions} name='selectedGroup' onChange={(e, data) => setSelectedGroup(data.value)} />
|
|
||||||
|
|
||||||
</Modal.Description>
|
|
||||||
|
|
||||||
</Modal.Content>
|
|
||||||
<Modal.Actions>
|
|
||||||
<Button onClick={()=> handleDone(onClose)} >
|
|
||||||
<Icon name='headphones' /> Listen
|
|
||||||
</Button>
|
|
||||||
</Modal.Actions>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
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 (
|
|
||||||
|
|
||||||
<Modal open={this.props.open} onClose={this.handleClose} size='tiny' >
|
|
||||||
<Modal.Header>Select a Group</Modal.Header>
|
|
||||||
<Modal.Content >
|
|
||||||
<Modal.Description>
|
|
||||||
<p>Choose the type of calls you want to listen to</p>
|
|
||||||
<Dropdown placeholder='Group...' fluid selection options={groupList} name='selectedGroup' onChange={this.handleInputChange} />
|
|
||||||
|
|
||||||
</Modal.Description>
|
|
||||||
|
|
||||||
</Modal.Content>
|
|
||||||
<Modal.Actions>
|
|
||||||
<Button onClick={this.handleDone} >
|
|
||||||
<Icon name='headphones' /> Listen
|
|
||||||
</Button>
|
|
||||||
</Modal.Actions>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
export default GroupModal;
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { Component, useState, useEffect } from "react";
|
import React, { Component, useState, useEffect } from "react";
|
||||||
import { useGetGroupsQuery, useGetSystemsQuery, } from '../../features/api/apiSlice'
|
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 { useSelector, useDispatch } from 'react-redux'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -15,11 +15,14 @@ import "./FilterModal.css";
|
|||||||
|
|
||||||
function GroupModal(props) {
|
function GroupModal(props) {
|
||||||
const shortName = useSelector((state) => state.callPlayer.shortName);
|
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: groupData, isSuccess } = useGetGroupsQuery(props.shortName);
|
||||||
const { data: allSystems } = useGetSystemsQuery();
|
const { data: allSystems } = useGetSystemsQuery();
|
||||||
const [selectedGroup, setSelectedGroup] = useState(false);
|
const [selectedGroup, setSelectedGroup] = useState(false);
|
||||||
const [groupOptions, setGroupOptions] = useState([]);
|
const [groupOptions, setGroupOptions] = useState([]);
|
||||||
const [centerCall, setLocalCenterCall] = useState(true);
|
const [localCenterCall, setLocalCenterCall] = useState(centerCall);
|
||||||
|
const [localBackgroundAutoplay, setLocalBackgroundAutoplay] = useState(backgroundAutoplay);
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const onClose = props.onClose;
|
const onClose = props.onClose;
|
||||||
let system = false;
|
let system = false;
|
||||||
@@ -30,7 +33,8 @@ function GroupModal(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleDone(onClose) {
|
function handleDone(onClose) {
|
||||||
dispatch(setCenterCall(centerCall));
|
dispatch(setCenterCall(localCenterCall));
|
||||||
|
dispatch(setBackgroundAutoplay(localBackgroundAutoplay));
|
||||||
if (selectedGroup && (selectedGroup!="all")) {
|
if (selectedGroup && (selectedGroup!="all")) {
|
||||||
dispatch(setGroupFilter(selectedGroup))
|
dispatch(setGroupFilter(selectedGroup))
|
||||||
|
|
||||||
@@ -83,7 +87,8 @@ function GroupModal(props) {
|
|||||||
<p>Choose the type of calls you want to listen to</p>
|
<p>Choose the type of calls you want to listen to</p>
|
||||||
<Form>
|
<Form>
|
||||||
<Form.Select placeholder='All Calls' fluid selection options={groupOptions} name='selectedGroup' onChange={(e, data) => setSelectedGroup(data.value)} />
|
<Form.Select placeholder='All Calls' fluid selection options={groupOptions} name='selectedGroup' onChange={(e, data) => setSelectedGroup(data.value)} />
|
||||||
<Form.Checkbox label='Center playing call ' checked={centerCall} onChange={(e, data) => setLocalCenterCall(data.value)} />
|
<Form.Checkbox label='Focus on call playing' checked={localCenterCall} onChange={(e, data) => setLocalCenterCall(data.checked)} />
|
||||||
|
<Form.Checkbox label='Background autoplay' checked={localBackgroundAutoplay} onChange={(e, data) => setLocalBackgroundAutoplay(data.checked)} />
|
||||||
</Form>
|
</Form>
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
</Grid.Row>
|
</Grid.Row>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const MediaPlayer = (props) => {
|
|||||||
const [playTime, setPlayTime] = useState(0);
|
const [playTime, setPlayTime] = useState(0);
|
||||||
const [isPlaying, setIsPlaying] = useState(false);
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
const parentHandlePlayPause = props.onPlayPause
|
const parentHandlePlayPause = props.onPlayPause
|
||||||
|
const playSilence = props.playSilence;
|
||||||
|
|
||||||
const handlePause = () => { setIsPlaying(false); }
|
const handlePause = () => { setIsPlaying(false); }
|
||||||
const handlePlay = () => { setIsPlaying(true); }
|
const handlePlay = () => { setIsPlaying(true); }
|
||||||
@@ -61,6 +62,38 @@ const MediaPlayer = (props) => {
|
|||||||
}
|
}
|
||||||
}, [call]);
|
}, [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 updatePlayProgress = () => {
|
||||||
const audio = audioRef.current.audioEl.current;
|
const audio = audioRef.current.audioEl.current;
|
||||||
const { currentTime, duration } = audio;
|
const { currentTime, duration } = audio;
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ const initialState = {
|
|||||||
currentCallId: false,
|
currentCallId: false,
|
||||||
playlist: [],
|
playlist: [],
|
||||||
live: false,
|
live: false,
|
||||||
centerCall: true
|
centerCall: true,
|
||||||
|
backgroundAutoplay: false
|
||||||
}
|
}
|
||||||
|
|
||||||
const compareCalls = (a, b) => {
|
const compareCalls = (a, b) => {
|
||||||
@@ -77,6 +78,9 @@ export const callPlayerSlice = createSlice({
|
|||||||
setCenterCall: (state,action) => {
|
setCenterCall: (state,action) => {
|
||||||
state.centerCall = action.payload;
|
state.centerCall = action.payload;
|
||||||
},
|
},
|
||||||
|
setBackgroundAutoplay: (state,action) => {
|
||||||
|
state.backgroundAutoplay = action.payload;
|
||||||
|
},
|
||||||
setShortName: (state, action) => {
|
setShortName: (state, action) => {
|
||||||
state.shortName = action.payload;
|
state.shortName = action.payload;
|
||||||
},
|
},
|
||||||
@@ -106,7 +110,7 @@ export const callPlayerSlice = createSlice({
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Action creators are generated for each case reducer function
|
// 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
|
export default callPlayerSlice.reducer
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user