index.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. import { jwtDecode, gql, backendURL, store } from '../App'
  2. const audio = new Audio()
  3. const actionTrackSet = (track, audio, playlist) =>
  4. ({
  5. type: 'SET_TRACK',
  6. track: track,
  7. playlist: playlist,
  8. duration: audio.duration,
  9. currentTime: audio.currentTime,
  10. volume: audio.volume
  11. })
  12. const actionTrackEject = () => ({type: 'EJECT_TRACK'})
  13. const actionTrackSetDuration = (time) => ({ type: 'SET_DURATION', duration: time })
  14. const actionTrackSetCurrTime = (time) => ({ type: 'SET_CURRTIME', currentTime: time })
  15. const actionTrackSetVolume = (value) => ({ type: 'SET_VOLUME', volume: value })
  16. const actionTrackPlay = () => ({ type: 'PLAY_TRACK' })
  17. const actionTrackPause = (currentTime) => ({ type: 'PAUSE_TRACK', currentTime: currentTime })
  18. const actionPlaylistSet = (playlist) => ({type: 'SET_PLAYLIST', playlist: playlist})
  19. const actionSetPlaylistIndex = (index) => ({type: 'SET_INDEX', playlistIndex: index})
  20. export const setPlaylist = (playlist) => dispatch => dispatch(actionPlaylistSet(playlist))
  21. export const setIndex = (index) => dispatch => dispatch(actionSetPlaylistIndex(index))
  22. export const setTrack = (track, playlist) =>
  23. dispatch => {
  24. audio.src = backendURL + '/' + track.url
  25. dispatch(actionTrackSet(track, audio, playlist))
  26. }
  27. export const switchTrack = (isForward, currentTrackIndex, playlist) =>
  28. dispatch => {
  29. let playlistLength = playlist.constructor.name ==='Array'? playlist.length - 1 : playlist.tracks.length - 1
  30. let tracks = playlist.constructor.name ==='Array'? playlist : playlist.tracks
  31. if (isForward ? currentTrackIndex < playlistLength : currentTrackIndex > 0) {
  32. dispatch(setTrack(tracks[currentTrackIndex + (isForward ? 1 : -1)], playlist))
  33. } else if (currentTrackIndex === (isForward ? playlistLength : 0)) {
  34. dispatch(setTrack(tracks[isForward ? 0 : playlistLength], playlist))
  35. }
  36. dispatch(playTrack())
  37. }
  38. export const playTrack = () =>
  39. dispatch => {
  40. dispatch(actionTrackPlay())
  41. audio.play()
  42. }
  43. export const pauseTrack = () =>
  44. dispatch => {
  45. dispatch(actionTrackPause(audio.currentTime))
  46. audio.pause()
  47. }
  48. export const setTrackVolume = (volume) =>
  49. dispatch => {
  50. audio.volume = volume
  51. dispatch(actionTrackSetVolume(volume))
  52. }
  53. export const setNewTrackCurrentTime = (time) =>
  54. (dispatch, getState) => {
  55. audio.pause()
  56. audio.currentTime = time
  57. getState().player.isPlaying? audio.play() : audio.pause()
  58. dispatch(actionTrackSetCurrTime(time))
  59. }
  60. audio.onended = () => store.dispatch(switchTrack(true, store.getState().player.playlistIndex, store.getState().player.playlist))
  61. audio.ondurationchange = (e) => store.dispatch(actionTrackSetDuration(e.target.duration))
  62. audio.ontimeupdate = (e) => store.dispatch(actionTrackSetCurrTime(e.target.currentTime))
  63. const actionPending = name => ({ type: 'PROMISE', status: 'PENDING', name })
  64. const actionResolved = (name, payload) => ({ type: 'PROMISE', status: 'RESOLVED', name, payload })
  65. const actionRejected = (name, error) => ({ type: 'PROMISE', status: 'REJECTED', name, error })
  66. export const actionPromise = (name, promise) =>
  67. async dispatch => {
  68. dispatch(actionPending(name))
  69. try {
  70. let payload = await promise
  71. dispatch(actionResolved(name, payload))
  72. return payload
  73. }
  74. catch (error) {
  75. dispatch(actionRejected(name, error))
  76. }
  77. }
  78. export const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
  79. export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
  80. export const actionFullLogout = () =>
  81. dispatch => {
  82. audio.pause()
  83. dispatch(actionTrackEject())
  84. dispatch(actionAuthLogout())
  85. }
  86. export const actionLogin = (login, password) =>
  87. actionPromise('login', gql(`
  88. query log($login:String!, $password:String!) {
  89. login(login: $login, password: $password)
  90. }`, { login, password }))
  91. export const actionFullLogin = (login = 'tst', password = '123') =>
  92. async dispatch => {
  93. let token = await dispatch(actionLogin(login, password))
  94. if (token) {
  95. await dispatch(actionAuthLogin(token))
  96. await dispatch(actionGetUserData())
  97. dispatch(actionGetUserPlaylists())
  98. dispatch(actionGetUserTracks())
  99. }
  100. }
  101. export const actionRegister = (login, password) =>
  102. actionPromise('registration', gql(`
  103. mutation register($login:String!, $password:String!) {
  104. createUser(login: $login, password: $password) {
  105. login, _id
  106. }
  107. }
  108. `, { login, password })
  109. )
  110. export const actionFullRegister = (login = 'tst', password = '123') =>
  111. async dispatch => {
  112. await dispatch(actionRegister(login, password))
  113. await dispatch(actionFullLogin(login, password))
  114. }
  115. export const actionGetUserData = () => {
  116. let _id = jwtDecode(localStorage.authToken).sub.id
  117. return (
  118. actionPromise('userData', gql(`
  119. query($userId: String!) {
  120. UserFindOne(query: $userId){
  121. login, _id, avatar {_id, url, originalFileName}
  122. }
  123. }
  124. `, { userId: JSON.stringify([{ _id }]) }))
  125. )
  126. }
  127. export const actionGetUserPlaylists = () => {
  128. let _id = jwtDecode(localStorage.authToken).sub.id
  129. return (
  130. actionPromise('userPlaylists', gql(`
  131. query getPlaylistByOwnerId($ownerId:String!) {
  132. PlaylistFind(query: $ownerId) {
  133. _id, name
  134. }
  135. }
  136. `, { ownerId: JSON.stringify([{ ___owner: _id }]) }))
  137. )
  138. }
  139. export const actionGetPlaylistById = (_id) =>
  140. actionPromise('playlistTracks', gql(`
  141. query playlistById($playlistId: String!) {
  142. PlaylistFind(query: $playlistId) {
  143. _id,
  144. name,
  145. tracks {
  146. _id, url, originalFileName,
  147. id3{ title, artist, album },
  148. }
  149. }
  150. }
  151. `, { playlistId: JSON.stringify([{ _id }]) }))
  152. export const actionGetUserTracks = () => {
  153. let _id = jwtDecode(localStorage.authToken).sub.id
  154. return (
  155. actionPromise('userTracks', gql(`
  156. query getUserTracks($ownerId: String!) {
  157. TrackFind(query: $ownerId) {
  158. _id, originalFileName, url,
  159. id3 { title, artist, album }
  160. }
  161. }
  162. `, { ownerId: JSON.stringify([{ ___owner: _id }]) }))
  163. )
  164. }
  165. export const actionAddPlaylist = playlistName =>
  166. async dispatch => {
  167. await dispatch(actionPromise('addPlaylist', gql(`
  168. mutation addPlaylist ($playlistName: String!){
  169. PlaylistUpsert(playlist: {name: $playlistName}) {
  170. _id, name
  171. }
  172. }
  173. `, { playlistName: playlistName })))
  174. dispatch(actionGetUserPlaylists())
  175. }
  176. export const actionLoadFile = (file, type) => {
  177. let fd = new FormData()
  178. console.log('TYPE', type)
  179. fd.append(type === 'upload' ? 'photo' : type, file)
  180. return (
  181. actionPromise('loadFile', fetch(backendURL + `/${type}`, {
  182. method: "POST",
  183. headers: localStorage.authToken ? { Authorization: 'Bearer ' + localStorage.authToken } : {},
  184. body: fd
  185. })
  186. .then(res => res.json())
  187. )
  188. )
  189. }
  190. export const actionUpdatePlaylist = (playlistId, updPlaylist) =>
  191. async dispatch => {
  192. await dispatch(actionPromise('trackToPlaylist', gql(`
  193. mutation($playlistId: ID, $newTracks: [TrackInput]) {
  194. PlaylistUpsert(playlist:{ _id: $playlistId, tracks: $newTracks}) {
  195. _id, name, tracks { _id, url, originalFileName, id3{ title, artist, album } }
  196. }
  197. }
  198. `, { playlistId: playlistId, newTracks: updPlaylist }))
  199. )
  200. await dispatch(actionGetPlaylistById(playlistId))
  201. }
  202. export const actionUploadUserTrack = (file, playlistId) =>
  203. async (dispatch, getState) => {
  204. await dispatch(actionLoadFile(file, 'track'))
  205. if (!playlistId) {
  206. await dispatch(actionGetUserTracks())
  207. if(getState().player.track && getState().player.playlist.constructor.name === 'Array') {
  208. console.log('HERE', getState().promise.userTracks.payload)
  209. dispatch(setPlaylist(getState().promise.userTracks.payload.reverse()))
  210. dispatch(setIndex(getState().player.playlist.map(item => item._id).indexOf(getState().player.track._id)))
  211. }
  212. } else {
  213. let updPlaylist = []
  214. let oldPlaylist = getState().promise.playlistTracks.payload[0].tracks
  215. if (oldPlaylist) oldPlaylist.forEach(track => updPlaylist.push({ _id: track._id }))
  216. updPlaylist.unshift({ _id: getState().promise.loadFile.payload?._id })
  217. await dispatch(actionUpdatePlaylist(playlistId, updPlaylist))
  218. if(getState().player.track && getState().player.playlist._id === playlistId) {
  219. dispatch(setPlaylist(getState().promise.trackToPlaylist.payload))
  220. dispatch(setIndex(updPlaylist.map(item => item._id).indexOf(getState().player.track._id)))
  221. }
  222. }
  223. }
  224. export const actionUploadAvatar = (file) =>
  225. async (dispatch, getState) => {
  226. await dispatch(actionLoadFile(file, 'upload'))
  227. await dispatch(actionPromise('setAvatar', gql(`
  228. mutation {
  229. UserUpsert(user:{_id: "${jwtDecode(localStorage.authToken).sub.id}", avatar: {_id: "${getState().promise?.loadFile?.payload?._id}"}}){
  230. _id, login, avatar{
  231. _id, url
  232. }
  233. }
  234. }
  235. `)))
  236. dispatch(actionGetUserData())
  237. }