Documentation

Tutorials: Station Playback

Setting a new source

The mutation is added to the setPlaybackSource.graphql file under src > graphql > mutations.



#import "../fragments/trackItem.graphql"
#import "../fragments/audioAdItem.graphql"
#import "../fragments/artistMessageItem.graphql"
#import "../fragments/customTrackItem.graphql"
#import "../fragments/idleTimeoutItem.graphql"
#import "../fragments/simStreamViolationItem.graphql"
#import "../fragments/voiceTrackItem.graphql"

mutation setPlaybackSource($deviceUuid: String!, $sourceId: String!) {
 playback {
   setSource (deviceUuid: $deviceUuid, sourceId: $sourceId) {
     id
     ... on StationSource {
       stationFactory {
         id
       }
     }
     current {
       sourceId
       ...trackItem
       ...audioAdItem
       ...artistMessageItem
       ...customTrackItem
       ...idleTimeoutItem
       ...simStreamViolationItem
       ...voiceTrackItem
     }
   }
 }
}

Fragments are used for the different playback source types, since these are reused in other queries and mutations.  To get a better understanding of the different types and when they would be used, head over to this section.

A provider was created that serves 2 main functions:

  1. Export the query in order for components to use the query as is
  2. Export a higher-order component that takes a Component and returns the component with the mutation function set as a property on the component.  This function can then be called to run the mutation.

These exports can be found in this file: src > graphql > playback > setPlaybackSource.jsx



import { graphql } from "react-apollo";
import { loader } from 'graphql.macro';
import { currentlyPlaying }  from './currentlyPlaying';
import { collectedStations }  from '../catalog/collectedStations';
const setPlaybackSource = loader('../mutations/setPlaybackSource.graphql');

const withSetPlaybackSource = graphql(setPlaybackSource, {
   name: 'setSource',
   props: ({ setSource, setSourceResult }) => {
     const { error } = setSourceResult;
     return {
       errorMessage: error && error.message,
       onNewSource: (deviceUuid, sourceId) => {
         setSource({ variables: { deviceUuid, sourceId } })
       },
     };
   },
   options: props => {
     return {
       update: (cache, { data: { playback: { setSource } }}) => {
         try {
           const cachedData = cache.readQuery({ query: currentlyPlaying, variables: { deviceUuid: props.deviceUuid } });
           const copyOfCache = { ...cachedData };
           copyOfCache.playback.current = setSource.current;
           cache.writeQuery({
             query: currentlyPlaying,
             variables: { deviceUuid: props.deviceUuid },
             data: copyOfCache
           });
         } catch (e) {}
       },
       refetchQueries: [
         { query: currentlyPlaying, variables: { deviceUuid: props.deviceUuid } },
         { query: collectedStations, variables: { deviceUuid: props.deviceUuid } }
       ],
     }
   }
 }
);

export { withSetPlaybackSource, setPlaybackSource };

In the above code example you will see that the mutation is imported and loaded with the graphql.macro library.  This library compiles GraphQL ASTs at build time using babel macros.

The provider (withSetPlaybackSource) is then created.  It takes a component as an argument and returns a new component with a property onNewSource that is set to the function to run the mutation.  Notice that it also updates the Apollo cache with the results returned from the mutation. Read more about these best practices.

The provider and the mutation is then both exported.