index.js 9.7 KB

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