Add chromecast seek bar and api, move volume component to separate file

This commit is contained in:
Michal Szczepanski 2020-03-08 18:08:43 +01:00
parent 3d1e78f9af
commit 250cf1f778
7 changed files with 119 additions and 20 deletions

@ -54,6 +54,12 @@ mutation {
}
`;
const SEEK = (uid, value) => gql`
mutation {
chromecastSeek(uid:"${uid}", value:${value})
}
`;
const MEDIA_STATUS = () => gql`
subscription {
mediaStatus {
@ -106,3 +112,7 @@ export const chromecastPlay = (uid) => client.mutate({
export const chromecastVolumeChange = (uid, volume) => client.mutate({
mutation: VOLUME_CHANGE(uid, volume),
});
export const chromecastSeek = (uid, value) => client.mutate({
mutation: SEEK(uid, value),
});

@ -1,27 +1,12 @@
import React, { useState, useEffect } from 'react';
import { Button, Card, Slider } from 'antd';
import { Button, Card } from 'antd';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPlayCircle, faPauseCircle } from '@fortawesome/free-regular-svg-icons';
import chromecastStore from '../store/chromecastStore';
import { chromecastPause, chromecastPlay } from '../service/chromecast';
import TimeDisplay from './timeDisplay';
import { chromecastPause, chromecastPlay, chromecastVolumeChange } from '../service/chromecast';
const VolumeComponent = ({ uid, volumeLevel }) => {
let id = null;
const handleVolumeChange = (value) => {
if (id) clearTimeout(id);
id = setTimeout(() => {
chromecastVolumeChange(uid, value * 0.01);
}, 500);
};
useEffect(() => () => clearTimeout(id));
return (
<Slider defaultValue={volumeLevel * 100} onChange={handleVolumeChange} />
);
};
import VolumeComponent from './volume';
import TimeProgressComponent from './timeProgress';
const ChromecastDeviceComponent = () => {
const [chromecastList, setChromecastList] = useState(chromecastStore.chromecast);
@ -77,6 +62,12 @@ const ChromecastDevice = ({ device }) => {
duration={status.duration}
playerState={status.playerState}
/>
<TimeProgressComponent
uid={device.uuid}
currentTime={status.currentTime}
duration={status.duration}
playerState={status.playerState}
/>
<VolumeComponent uid={device.uuid} volumeLevel={castStatus.volumeLevel} />
<Button type="link" icon={<FontAwesomeIcon icon={faPauseCircle} onClick={handlePauseClick} size="2x" />} />
</div>
@ -91,6 +82,12 @@ const ChromecastDevice = ({ device }) => {
duration={status.duration}
playerState={status.playerState}
/>
<TimeProgressComponent
uid={device.uuid}
currentTime={status.currentTime}
duration={status.duration}
playerState={status.playerState}
/>
<VolumeComponent uid={device.uuid} volumeLevel={castStatus.volumeLevel} />
<Button type="link" icon={<FontAwesomeIcon icon={faPlayCircle} onClick={handlePlayClick} size="2x" />} />
</div>

@ -11,7 +11,10 @@ const TimeDisplay = ({ currentTime, duration, playerState }) => {
if (playerState === 'PLAYING') {
useEffect(() => {
const timer = setTimeout(() => {
const current = timeData[2] + 1;
let current = timeData[2] + 1;
if (Math.abs(current - currentTime) > 10) {
current = Math.round(currentTime);
}
setTimeData([
movieTimeFormat(current),
movieTimeFormat(Math.round(duration)),

@ -0,0 +1,47 @@
import React, { useState, useEffect } from 'react';
import { Slider } from 'antd';
import { chromecastSeek } from '../service/chromecast';
import movieTimeFormat from '../formatter/movieTimeFormat';
const TimeProgressComponent = ({
uid,
currentTime,
duration,
playerState,
}) => {
const [time, setTime] = useState(Math.floor(currentTime));
if (playerState === 'PLAYING') {
useEffect(() => {
const timer = setTimeout(() => {
let current = time + 1;
if (Math.abs(current - currentTime) > 10) {
current = Math.round(currentTime);
}
setTime(current);
}, 1000);
return () => clearTimeout(timer);
});
}
const handleSeek = (value) => {
chromecastSeek(uid, value);
};
const handleChange = (value) => {
setTime(value);
};
return (
<Slider
max={Math.floor(duration)}
value={time}
onChange={handleChange}
onAfterChange={handleSeek}
tipFormatter={movieTimeFormat}
/>
);
};
export default TimeProgressComponent;

@ -0,0 +1,21 @@
import React, { useEffect } from 'react';
import { Slider } from 'antd';
import { chromecastVolumeChange } from '../service/chromecast';
const VolumeComponent = ({ uid, volumeLevel }) => {
let id = null;
const handleVolumeChange = (value) => {
if (id) clearTimeout(id);
id = setTimeout(() => {
chromecastVolumeChange(uid, value * 0.01);
}, 500);
};
useEffect(() => () => clearTimeout(id));
return (
<Slider defaultValue={volumeLevel * 100} onChange={handleVolumeChange} />
);
};
export default VolumeComponent;

@ -141,6 +141,26 @@ class ChromecastVolumeChange(graphene.Mutation):
data.device.set_volume(volume)
return True
class ChromecastSeek(graphene.Mutation):
"""Chromecast volume change"""
class Arguments:
"""Chromecast volume change uid and volume float value"""
uid = graphene.String(required=True)
value = graphene.Float(required=True)
Output = graphene.Boolean
def mutate(self,
info: ResolveInfo,
uid: graphene.String,
value: graphene.Float) -> graphene.Boolean: # pylint: disable=W0622
"""Method to volume change uid and volume float value"""
if uid not in cache.CHROMECAST:
raise error.ChromecastUUIDError(uid=uid)
data = cache.CHROMECAST[uid]
data.device.media_controller.seek(value)
return True
class ChromecastDevice:
"""Device with api and interface data"""

@ -18,3 +18,4 @@ class Mutation(graphene.ObjectType):
chromecastPause = chromecast.ChromecastPause.Field()
chromecastPlay = chromecast.ChromecastPlay.Field()
chromecastVolumeChange = chromecast.ChromecastVolumeChange.Field()
chromecastSeek = chromecast.ChromecastSeek.Field()