index.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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 actionTrackSetDuration = (time) => ({ type: 'SET_DURATION', duration: time })
  13. const actionTrackSetCurrTime = (time) => ({ type: 'SET_CURRTIME', currentTime: time })
  14. const actionTrackSetVolume = (value) => ({ type: 'SET_VOLUME', volume: value })
  15. const actionTrackPlay = () => ({ type: 'PLAY_TRACK' })
  16. const actionTrackPause = (currentTime) => ({ type: 'PAUSE_TRACK', currentTime: currentTime })
  17. const actionPlaylistSet = (playlist) => ({type: 'SET_PLAYLIST', playlist: playlist})
  18. const actionSetPlaylistIndex = (index) => ({type: 'SET_INDEX', playlistIndex: index})
  19. export const setPlaylist = (playlist) => dispatch => dispatch(actionPlaylistSet(playlist))
  20. export const setIndex = (index) => dispatch => dispatch(actionSetPlaylistIndex(index))
  21. export const setTrack = (track, playlist) =>
  22. dispatch => {
  23. audio.src = backendURL + '/' + track.url
  24. dispatch(actionTrackSet(track, audio, playlist))
  25. }
  26. export const switchTrack = (isForward, currentTrackIndex, playlist) =>
  27. dispatch => {
  28. let playlistLength = playlist.constructor.name ==='Array'? playlist.length - 1 : playlist.tracks.length - 1
  29. let tracks = playlist.constructor.name ==='Array'? playlist : playlist.tracks
  30. console.log('stuff', tracks, playlistLength)
  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 actionLogin = (login, password) =>
  81. actionPromise('login', gql(`
  82. query log($login:String!, $password:String!) {
  83. login(login: $login, password: $password)
  84. }`, { login, password }))
  85. export const actionFullLogin = (login = 'tst', password = '123') =>
  86. async dispatch => {
  87. let token = await dispatch(actionLogin(login, password))
  88. if (token) {
  89. await dispatch(actionAuthLogin(token))
  90. await dispatch(actionGetUserData())
  91. dispatch(actionGetUserPlaylists())
  92. dispatch(actionGetUserTracks())
  93. }
  94. }
  95. export const actionRegister = (login, password) =>
  96. actionPromise('registration', gql(`
  97. mutation register($login:String!, $password:String!) {
  98. createUser(login: $login, password: $password) {
  99. login, _id
  100. }
  101. }
  102. `, { login, password })
  103. )
  104. export const actionFullRegister = (login = 'tst', password = '123') =>
  105. async dispatch => {
  106. await dispatch(actionRegister(login, password))
  107. await dispatch(actionFullLogin(login, password))
  108. }
  109. export const actionGetUserData = () => {
  110. let _id = jwtDecode(localStorage.authToken).sub.id
  111. return (
  112. actionPromise('userData', gql(`
  113. query($userId: String!) {
  114. UserFindOne(query: $userId){
  115. login, _id, avatar {_id, url, originalFileName}
  116. }
  117. }
  118. `, { userId: JSON.stringify([{ _id }]) }))
  119. )
  120. }
  121. export const actionGetUserPlaylists = () => {
  122. let _id = jwtDecode(localStorage.authToken).sub.id
  123. return (
  124. actionPromise('userPlaylists', gql(`
  125. query getPlaylistByOwnerId($ownerId:String!) {
  126. PlaylistFind(query: $ownerId) {
  127. _id, name
  128. }
  129. }
  130. `, { ownerId: JSON.stringify([{ ___owner: _id }]) }))
  131. )
  132. }
  133. export const actionGetPlaylistById = (_id) =>
  134. actionPromise('playlistTracks', gql(`
  135. query playlistById($playlistId: String!) {
  136. PlaylistFind(query: $playlistId) {
  137. _id,
  138. name,
  139. tracks {
  140. _id, url, originalFileName,
  141. id3{ title, artist, album },
  142. }
  143. }
  144. }
  145. `, { playlistId: JSON.stringify([{ _id }]) }))
  146. export const actionGetUserTracks = () => {
  147. let _id = jwtDecode(localStorage.authToken).sub.id
  148. return (
  149. actionPromise('userTracks', gql(`
  150. query getUserTracks($ownerId: String!) {
  151. TrackFind(query: $ownerId) {
  152. _id, originalFileName, url,
  153. id3 { title, artist, album }
  154. }
  155. }
  156. `, { ownerId: JSON.stringify([{ ___owner: _id }]) }))
  157. )
  158. }
  159. export const actionAddPlaylist = playlistName =>
  160. async dispatch => {
  161. await dispatch(actionPromise('addPlaylist', gql(`
  162. mutation addPlaylist ($playlistName: String!){
  163. PlaylistUpsert(playlist: {name: $playlistName}) {
  164. _id, name
  165. }
  166. }
  167. `, { playlistName: playlistName })))
  168. dispatch(actionGetUserPlaylists())
  169. }
  170. export const actionLoadFile = (file, type) => {
  171. let fd = new FormData()
  172. console.log('TYPE', type)
  173. fd.append(type === 'upload' ? 'photo' : type, file)
  174. return (
  175. actionPromise('loadFile', fetch(backendURL + `/${type}`, {
  176. method: "POST",
  177. headers: localStorage.authToken ? { Authorization: 'Bearer ' + localStorage.authToken } : {},
  178. body: fd
  179. })
  180. .then(res => res.json())
  181. )
  182. )
  183. }
  184. export const actionUpdatePlaylist = (playlistId, updPlaylist) =>
  185. async dispatch => {
  186. await dispatch(actionPromise('trackToPlaylist', gql(`
  187. mutation($playlistId: ID, $newTracks: [TrackInput]) {
  188. PlaylistUpsert(playlist:{ _id: $playlistId, tracks: $newTracks}) {
  189. _id, name, tracks { _id, url, originalFileName, id3{ title, artist, album } }
  190. }
  191. }
  192. `, { playlistId: playlistId, newTracks: updPlaylist }))
  193. )
  194. await dispatch(actionGetPlaylistById(playlistId))
  195. }
  196. export const actionUploadUserTrack = (file, playlistId) =>
  197. async (dispatch, getState) => {
  198. await dispatch(actionLoadFile(file, 'track'))
  199. if (!playlistId) {
  200. await dispatch(actionGetUserTracks())
  201. if(getState().player.track && getState().player.playlist.constructor.name === 'Array') {
  202. console.log('HERE', getState().promise.userTracks.payload)
  203. dispatch(setPlaylist(getState().promise.userTracks.payload.reverse()))
  204. dispatch(setIndex(getState().player.playlist.map(item => item._id).indexOf(getState().player.track._id)))
  205. }
  206. } else {
  207. let updPlaylist = []
  208. let oldPlaylist = getState().promise.playlistTracks.payload[0].tracks
  209. if (oldPlaylist) oldPlaylist.forEach(track => updPlaylist.push({ _id: track._id }))
  210. updPlaylist.unshift({ _id: getState().promise.loadFile.payload?._id })
  211. await dispatch(actionUpdatePlaylist(playlistId, updPlaylist))
  212. if(getState().player.track && getState().player.playlist._id === playlistId) {
  213. dispatch(setPlaylist(getState().promise.trackToPlaylist.payload))
  214. dispatch(setIndex(updPlaylist.map(item => item._id).indexOf(getState().player.track._id)))
  215. }
  216. }
  217. }
  218. export const actionUploadAvatar = (file) =>
  219. async (dispatch, getState) => {
  220. await dispatch(actionLoadFile(file, 'upload'))
  221. await dispatch(actionPromise('setAvatar', gql(`
  222. mutation {
  223. UserUpsert(user:{_id: "${jwtDecode(localStorage.authToken).sub.id}", avatar: {_id: "${getState().promise?.loadFile?.payload?._id}"}}){
  224. _id, login, avatar{
  225. _id, url
  226. }
  227. }
  228. }
  229. `)))
  230. dispatch(actionGetUserData())
  231. }