You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

actions.js 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /* @flow */
  2. import { getShareInfoText } from '../invite';
  3. import {
  4. SET_GOOGLE_API_PROFILE,
  5. SET_GOOGLE_API_STATE
  6. } from './actionTypes';
  7. import { GOOGLE_API_STATES } from './constants';
  8. import googleApi from './googleApi';
  9. /**
  10. * Retrieves the current calendar events.
  11. *
  12. * @param {number} fetchStartDays - The number of days to go back when fetching.
  13. * @param {number} fetchEndDays - The number of days to fetch.
  14. * @returns {function(Dispatch<*>): Promise<CalendarEntries>}
  15. */
  16. export function getCalendarEntries(
  17. fetchStartDays: ?number, fetchEndDays: ?number) {
  18. return () =>
  19. googleApi.get()
  20. .then(() =>
  21. googleApi._getCalendarEntries(fetchStartDays, fetchEndDays));
  22. }
  23. /**
  24. * Loads Google API.
  25. *
  26. * @param {string} clientId - The client ID to be used with the API library.
  27. * @returns {Function}
  28. */
  29. export function loadGoogleAPI(clientId: string) {
  30. return (dispatch: Dispatch<*>, getState: Function) =>
  31. googleApi.get()
  32. .then(() => {
  33. if (getState()['features/google-api'].googleAPIState
  34. === GOOGLE_API_STATES.NEEDS_LOADING) {
  35. return googleApi.initializeClient(clientId);
  36. }
  37. return Promise.resolve();
  38. })
  39. .then(() => dispatch({
  40. type: SET_GOOGLE_API_STATE,
  41. googleAPIState: GOOGLE_API_STATES.LOADED }))
  42. .then(() => googleApi.isSignedIn())
  43. .then(isSignedIn => {
  44. if (isSignedIn) {
  45. dispatch({
  46. type: SET_GOOGLE_API_STATE,
  47. googleAPIState: GOOGLE_API_STATES.SIGNED_IN });
  48. }
  49. });
  50. }
  51. /**
  52. * Executes a request for a list of all YouTube broadcasts associated with
  53. * user currently signed in to the Google API Client Library.
  54. *
  55. * @returns {function(): (Promise<*>|Promise<any[] | never>)}
  56. */
  57. export function requestAvailableYouTubeBroadcasts() {
  58. return () =>
  59. googleApi.requestAvailableYouTubeBroadcasts()
  60. .then(response => {
  61. // Takes in a list of broadcasts from the YouTube API,
  62. // removes dupes, removes broadcasts that cannot get a stream key,
  63. // and parses the broadcasts into flat objects.
  64. const broadcasts = response.result.items;
  65. const parsedBroadcasts = {};
  66. for (let i = 0; i < broadcasts.length; i++) {
  67. const broadcast = broadcasts[i];
  68. const boundStreamID = broadcast.contentDetails.boundStreamId;
  69. if (boundStreamID && !parsedBroadcasts[boundStreamID]) {
  70. parsedBroadcasts[boundStreamID] = {
  71. boundStreamID,
  72. id: broadcast.id,
  73. status: broadcast.status.lifeCycleStatus,
  74. title: broadcast.snippet.title
  75. };
  76. }
  77. }
  78. return Object.values(parsedBroadcasts);
  79. });
  80. }
  81. /**
  82. * Fetches the stream key for a YouTube broadcast and updates the internal
  83. * state to display the associated stream key as being entered.
  84. *
  85. * @param {string} boundStreamID - The bound stream ID associated with the
  86. * broadcast from which to get the stream key.
  87. * @returns {function(): (Promise<*>|Promise<{
  88. * streamKey: (*|string),
  89. * selectedBoundStreamID: *} | never>)}
  90. */
  91. export function requestLiveStreamsForYouTubeBroadcast(boundStreamID: string) {
  92. return () =>
  93. googleApi.requestLiveStreamsForYouTubeBroadcast(boundStreamID)
  94. .then(response => {
  95. const broadcasts = response.result.items;
  96. const streamName = broadcasts
  97. && broadcasts[0]
  98. && broadcasts[0].cdn.ingestionInfo.streamName;
  99. const streamKey = streamName || '';
  100. return {
  101. streamKey,
  102. selectedBoundStreamID: boundStreamID
  103. };
  104. });
  105. }
  106. /**
  107. * Forces the Google web client application to prompt for a sign in, such as
  108. * when changing account, and will then fetch available YouTube broadcasts.
  109. *
  110. * @returns {function(): (Promise<*>|Promise<{
  111. * streamKey: (*|string),
  112. * selectedBoundStreamID: *} | never>)}
  113. */
  114. export function showAccountSelection() {
  115. return () =>
  116. googleApi.showAccountSelection();
  117. }
  118. /**
  119. * Prompts the participant to sign in to the Google API Client Library.
  120. *
  121. * @returns {function(Dispatch<*>): Promise<string | never>}
  122. */
  123. export function signIn() {
  124. return (dispatch: Dispatch<*>) => googleApi.get()
  125. .then(() => googleApi.signInIfNotSignedIn())
  126. .then(() => dispatch({
  127. type: SET_GOOGLE_API_STATE,
  128. googleAPIState: GOOGLE_API_STATES.SIGNED_IN
  129. }));
  130. }
  131. /**
  132. * Logs out the user.
  133. *
  134. * @returns {function(Dispatch<*>): Promise<string | never>}
  135. */
  136. export function signOut() {
  137. return (dispatch: Dispatch<*>) =>
  138. googleApi.get()
  139. .then(() => googleApi.signOut())
  140. .then(() => {
  141. dispatch({
  142. type: SET_GOOGLE_API_STATE,
  143. googleAPIState: GOOGLE_API_STATES.LOADED
  144. });
  145. dispatch({
  146. type: SET_GOOGLE_API_PROFILE,
  147. profileEmail: ''
  148. });
  149. });
  150. }
  151. /**
  152. * Updates the profile data that is currently used.
  153. *
  154. * @returns {function(Dispatch<*>): Promise<string | never>}
  155. */
  156. export function updateProfile() {
  157. return (dispatch: Dispatch<*>) => googleApi.get()
  158. .then(() => googleApi.signInIfNotSignedIn())
  159. .then(() => dispatch({
  160. type: SET_GOOGLE_API_STATE,
  161. googleAPIState: GOOGLE_API_STATES.SIGNED_IN
  162. }))
  163. .then(() => googleApi.getCurrentUserProfile())
  164. .then(profile => {
  165. dispatch({
  166. type: SET_GOOGLE_API_PROFILE,
  167. profileEmail: profile.getEmail()
  168. });
  169. return profile.getEmail();
  170. });
  171. }
  172. /**
  173. * Updates the calendar event and adds a location and text.
  174. *
  175. * @param {string} id - The event id to update.
  176. * @param {string} calendarId - The calendar id to use.
  177. * @param {string} location - The location to add to the event.
  178. * @returns {function(Dispatch<*>): Promise<string | never>}
  179. */
  180. export function updateCalendarEvent(
  181. id: string, calendarId: string, location: string) {
  182. return (dispatch: Dispatch<*>, getState: Function) => {
  183. const { dialInNumbersUrl } = getState()['features/base/config'];
  184. const text = getShareInfoText(location, dialInNumbersUrl !== undefined);
  185. return googleApi.get()
  186. .then(() =>
  187. googleApi._updateCalendarEntry(id, calendarId, location, text));
  188. };
  189. }