Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

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