import { jwtDecode, gql, backendURL, store } from '../App' const audio = new Audio() const actionTrackSet = (track, audio, playlist) => ({ type: 'SET_TRACK', track: track, playlist: playlist, duration: audio.duration, currentTime: audio.currentTime, volume: audio.volume }) const actionTrackSetDuration = (time) => ({ type: 'SET_DURATION', duration: time }) const actionTrackSetCurrTime = (time) => ({ type: 'SET_CURRTIME', currentTime: time }) const actionTrackSetVolume = (value) => ({ type: 'SET_VOLUME', volume: value }) const actionTrackPlay = () => ({ type: 'PLAY_TRACK' }) const actionTrackPause = (currentTime) => ({ type: 'PAUSE_TRACK', currentTime: currentTime }) const actionPlaylistSet = (playlist) => ({type: 'SET_PLAYLIST', playlist: playlist}) const actionSetPlaylistIndex = (index) => ({type: 'SET_INDEX', playlistIndex: index}) export const setPlaylist = (playlist) => dispatch => dispatch(actionPlaylistSet(playlist)) export const setIndex = (index) => dispatch => dispatch(actionSetPlaylistIndex(index)) export const setTrack = (track, playlist) => dispatch => { audio.src = backendURL + '/' + track.url dispatch(actionTrackSet(track, audio, playlist)) } export const switchTrack = (isForward, currentTrackIndex, playlist) => dispatch => { let playlistLength = playlist.constructor.name ==='Array'? playlist.length - 1 : playlist.tracks.length - 1 let tracks = playlist.constructor.name ==='Array'? playlist : playlist.tracks console.log('stuff', tracks, playlistLength) if (isForward ? currentTrackIndex < playlistLength : currentTrackIndex > 0) { dispatch(setTrack(tracks[currentTrackIndex + (isForward ? 1 : -1)], playlist)) } else if (currentTrackIndex === (isForward ? playlistLength : 0)) { dispatch(setTrack(tracks[isForward ? 0 : playlistLength], playlist)) } dispatch(playTrack()) } export const playTrack = () => dispatch => { dispatch(actionTrackPlay()) audio.play() } export const pauseTrack = () => dispatch => { dispatch(actionTrackPause(audio.currentTime)) audio.pause() } export const setTrackVolume = (volume) => dispatch => { audio.volume = volume dispatch(actionTrackSetVolume(volume)) } export const setNewTrackCurrentTime = (time) => (dispatch, getState) => { audio.pause() audio.currentTime = time getState().player.isPlaying? audio.play() : audio.pause() dispatch(actionTrackSetCurrTime(time)) } audio.onended = () => store.dispatch(switchTrack(true, store.getState().player.playlistIndex, store.getState().player.playlist)) audio.ondurationchange = (e) => store.dispatch(actionTrackSetDuration(e.target.duration)) audio.ontimeupdate = (e) => store.dispatch(actionTrackSetCurrTime(e.target.currentTime)) const actionPending = name => ({ type: 'PROMISE', status: 'PENDING', name }) const actionResolved = (name, payload) => ({ type: 'PROMISE', status: 'RESOLVED', name, payload }) const actionRejected = (name, error) => ({ type: 'PROMISE', status: 'REJECTED', name, error }) export const actionPromise = (name, promise) => async dispatch => { dispatch(actionPending(name)) try { let payload = await promise dispatch(actionResolved(name, payload)) return payload } catch (error) { dispatch(actionRejected(name, error)) } } export const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token }) export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' }) export const actionLogin = (login, password) => actionPromise('login', gql(` query log($login:String!, $password:String!) { login(login: $login, password: $password) }`, { login, password })) export const actionFullLogin = (login = 'tst', password = '123') => async dispatch => { let token = await dispatch(actionLogin(login, password)) if (token) { await dispatch(actionAuthLogin(token)) await dispatch(actionGetUserData()) dispatch(actionGetUserPlaylists()) dispatch(actionGetUserTracks()) } } export const actionRegister = (login, password) => actionPromise('registration', gql(` mutation register($login:String!, $password:String!) { createUser(login: $login, password: $password) { login, _id } } `, { login, password }) ) export const actionFullRegister = (login = 'tst', password = '123') => async dispatch => { await dispatch(actionRegister(login, password)) await dispatch(actionFullLogin(login, password)) } export const actionGetUserData = () => { let _id = jwtDecode(localStorage.authToken).sub.id return ( actionPromise('userData', gql(` query($userId: String!) { UserFindOne(query: $userId){ login, _id, avatar {_id, url, originalFileName} } } `, { userId: JSON.stringify([{ _id }]) })) ) } export const actionGetUserPlaylists = () => { let _id = jwtDecode(localStorage.authToken).sub.id return ( actionPromise('userPlaylists', gql(` query getPlaylistByOwnerId($ownerId:String!) { PlaylistFind(query: $ownerId) { _id, name } } `, { ownerId: JSON.stringify([{ ___owner: _id }]) })) ) } export const actionGetPlaylistById = (_id) => actionPromise('playlistTracks', gql(` query playlistById($playlistId: String!) { PlaylistFind(query: $playlistId) { _id, name, tracks { _id, url, originalFileName, id3{ title, artist, album }, } } } `, { playlistId: JSON.stringify([{ _id }]) })) export const actionGetUserTracks = () => { let _id = jwtDecode(localStorage.authToken).sub.id return ( actionPromise('userTracks', gql(` query getUserTracks($ownerId: String!) { TrackFind(query: $ownerId) { _id, originalFileName, url, id3 { title, artist, album } } } `, { ownerId: JSON.stringify([{ ___owner: _id }]) })) ) } export const actionAddPlaylist = playlistName => async dispatch => { await dispatch(actionPromise('addPlaylist', gql(` mutation addPlaylist ($playlistName: String!){ PlaylistUpsert(playlist: {name: $playlistName}) { _id, name } } `, { playlistName: playlistName }))) dispatch(actionGetUserPlaylists()) } export const actionLoadFile = (file, type) => { let fd = new FormData() console.log('TYPE', type) fd.append(type === 'upload' ? 'photo' : type, file) return ( actionPromise('loadFile', fetch(backendURL + `/${type}`, { method: "POST", headers: localStorage.authToken ? { Authorization: 'Bearer ' + localStorage.authToken } : {}, body: fd }) .then(res => res.json()) ) ) } export const actionUpdatePlaylist = (playlistId, updPlaylist) => async dispatch => { await dispatch(actionPromise('trackToPlaylist', gql(` mutation($playlistId: ID, $newTracks: [TrackInput]) { PlaylistUpsert(playlist:{ _id: $playlistId, tracks: $newTracks}) { _id, name, tracks { _id, originalFileName, } } } `, { playlistId: playlistId, newTracks: updPlaylist })) ) await dispatch(actionGetPlaylistById(playlistId)) } export const actionUploadUserTrack = (file, playlistId) => async (dispatch, getState) => { await dispatch(actionLoadFile(file, 'track')) if (!playlistId) { dispatch(actionGetUserTracks()) } else { console.log('UPLOADING TO PLAYLIS') let updPlaylist = [] let oldPlaylist = getState().promise.playlistTracks.payload[0].tracks if (oldPlaylist) { //console.log('id pashet', oldPlaylist) oldPlaylist.forEach(track => updPlaylist.push({ _id: track._id })) } updPlaylist.unshift({ _id: getState().promise.loadFile.payload?._id }) console.log('UPDATED PLST', updPlaylist) await dispatch(actionUpdatePlaylist(playlistId, updPlaylist)) } } export const actionUploadAvatar = (file) => async (dispatch, getState) => { await dispatch(actionLoadFile(file, 'upload')) await dispatch(actionPromise('setAvatar', gql(` mutation { UserUpsert(user:{_id: "${jwtDecode(localStorage.authToken).sub.id}", avatar: {_id: "${getState().promise?.loadFile?.payload?._id}"}}){ _id, login, avatar{ _id, url } } } `))) dispatch(actionGetUserData()) }