background autoplaying

This commit is contained in:
Luke Berndt
2023-02-15 21:28:30 -05:00
parent b5a610eb4d
commit b8ba705aee
5 changed files with 69 additions and 161 deletions

View File

@@ -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) {
<Menu fixed="bottom" compact inverted >
<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.Item><SupportModal /></Menu.Item>
<Menu.Item><a href={callDownload}><Icon name="download" />Download</a></Menu.Item>

View File

@@ -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;

View File

@@ -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) {
<p>Choose the type of calls you want to listen to</p>
<Form>
<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>
</Grid.Column>
</Grid.Row>

View File

@@ -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;

View File

@@ -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