Add chromecast seek bar and api, move volume component to separate file
This commit is contained in:
parent
3d1e78f9af
commit
250cf1f778
@ -54,6 +54,12 @@ mutation {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const SEEK = (uid, value) => gql`
|
||||||
|
mutation {
|
||||||
|
chromecastSeek(uid:"${uid}", value:${value})
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const MEDIA_STATUS = () => gql`
|
const MEDIA_STATUS = () => gql`
|
||||||
subscription {
|
subscription {
|
||||||
mediaStatus {
|
mediaStatus {
|
||||||
@ -106,3 +112,7 @@ export const chromecastPlay = (uid) => client.mutate({
|
|||||||
export const chromecastVolumeChange = (uid, volume) => client.mutate({
|
export const chromecastVolumeChange = (uid, volume) => client.mutate({
|
||||||
mutation: VOLUME_CHANGE(uid, volume),
|
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 React, { useState, useEffect } from 'react';
|
||||||
import { Button, Card, Slider } from 'antd';
|
import { Button, Card } from 'antd';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faPlayCircle, faPauseCircle } from '@fortawesome/free-regular-svg-icons';
|
import { faPlayCircle, faPauseCircle } from '@fortawesome/free-regular-svg-icons';
|
||||||
import chromecastStore from '../store/chromecastStore';
|
import chromecastStore from '../store/chromecastStore';
|
||||||
|
import { chromecastPause, chromecastPlay } from '../service/chromecast';
|
||||||
import TimeDisplay from './timeDisplay';
|
import TimeDisplay from './timeDisplay';
|
||||||
import { chromecastPause, chromecastPlay, chromecastVolumeChange } from '../service/chromecast';
|
import VolumeComponent from './volume';
|
||||||
|
import TimeProgressComponent from './timeProgress';
|
||||||
|
|
||||||
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} />
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ChromecastDeviceComponent = () => {
|
const ChromecastDeviceComponent = () => {
|
||||||
const [chromecastList, setChromecastList] = useState(chromecastStore.chromecast);
|
const [chromecastList, setChromecastList] = useState(chromecastStore.chromecast);
|
||||||
@ -77,6 +62,12 @@ const ChromecastDevice = ({ device }) => {
|
|||||||
duration={status.duration}
|
duration={status.duration}
|
||||||
playerState={status.playerState}
|
playerState={status.playerState}
|
||||||
/>
|
/>
|
||||||
|
<TimeProgressComponent
|
||||||
|
uid={device.uuid}
|
||||||
|
currentTime={status.currentTime}
|
||||||
|
duration={status.duration}
|
||||||
|
playerState={status.playerState}
|
||||||
|
/>
|
||||||
<VolumeComponent uid={device.uuid} volumeLevel={castStatus.volumeLevel} />
|
<VolumeComponent uid={device.uuid} volumeLevel={castStatus.volumeLevel} />
|
||||||
<Button type="link" icon={<FontAwesomeIcon icon={faPauseCircle} onClick={handlePauseClick} size="2x" />} />
|
<Button type="link" icon={<FontAwesomeIcon icon={faPauseCircle} onClick={handlePauseClick} size="2x" />} />
|
||||||
</div>
|
</div>
|
||||||
@ -91,6 +82,12 @@ const ChromecastDevice = ({ device }) => {
|
|||||||
duration={status.duration}
|
duration={status.duration}
|
||||||
playerState={status.playerState}
|
playerState={status.playerState}
|
||||||
/>
|
/>
|
||||||
|
<TimeProgressComponent
|
||||||
|
uid={device.uuid}
|
||||||
|
currentTime={status.currentTime}
|
||||||
|
duration={status.duration}
|
||||||
|
playerState={status.playerState}
|
||||||
|
/>
|
||||||
<VolumeComponent uid={device.uuid} volumeLevel={castStatus.volumeLevel} />
|
<VolumeComponent uid={device.uuid} volumeLevel={castStatus.volumeLevel} />
|
||||||
<Button type="link" icon={<FontAwesomeIcon icon={faPlayCircle} onClick={handlePlayClick} size="2x" />} />
|
<Button type="link" icon={<FontAwesomeIcon icon={faPlayCircle} onClick={handlePlayClick} size="2x" />} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,7 +11,10 @@ const TimeDisplay = ({ currentTime, duration, playerState }) => {
|
|||||||
if (playerState === 'PLAYING') {
|
if (playerState === 'PLAYING') {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
const current = timeData[2] + 1;
|
let current = timeData[2] + 1;
|
||||||
|
if (Math.abs(current - currentTime) > 10) {
|
||||||
|
current = Math.round(currentTime);
|
||||||
|
}
|
||||||
setTimeData([
|
setTimeData([
|
||||||
movieTimeFormat(current),
|
movieTimeFormat(current),
|
||||||
movieTimeFormat(Math.round(duration)),
|
movieTimeFormat(Math.round(duration)),
|
||||||
|
47
frontend/src/view/timeProgress.jsx
Normal file
47
frontend/src/view/timeProgress.jsx
Normal file
@ -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;
|
21
frontend/src/view/volume.jsx
Normal file
21
frontend/src/view/volume.jsx
Normal file
@ -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)
|
data.device.set_volume(volume)
|
||||||
return True
|
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:
|
class ChromecastDevice:
|
||||||
"""Device with api and interface data"""
|
"""Device with api and interface data"""
|
||||||
|
@ -18,3 +18,4 @@ class Mutation(graphene.ObjectType):
|
|||||||
chromecastPause = chromecast.ChromecastPause.Field()
|
chromecastPause = chromecast.ChromecastPause.Field()
|
||||||
chromecastPlay = chromecast.ChromecastPlay.Field()
|
chromecastPlay = chromecast.ChromecastPlay.Field()
|
||||||
chromecastVolumeChange = chromecast.ChromecastVolumeChange.Field()
|
chromecastVolumeChange = chromecast.ChromecastVolumeChange.Field()
|
||||||
|
chromecastSeek = chromecast.ChromecastSeek.Field()
|
||||||
|
Loading…
Reference in New Issue
Block a user