diff --git a/jam-ui/src/components/dashboard/JKDashboardMain.js b/jam-ui/src/components/dashboard/JKDashboardMain.js index 0736dcbca..53da4ab69 100644 --- a/jam-ui/src/components/dashboard/JKDashboardMain.js +++ b/jam-ui/src/components/dashboard/JKDashboardMain.js @@ -160,6 +160,7 @@ function JKDashboardMain() { registerFriendRequest(); registerFriendRequestAccepted(); registerChatMessageCallback(); + registerSubscriptionCallback(); scriptLoaded.current = true; }; @@ -242,6 +243,14 @@ function JKDashboardMain() { }); }; + const registerSubscriptionCallback = () => { + window.JK.JamServer.registerMessageCallback(window.JK.MessageType.SUBSCRIPTION_MESSAGE, function(header, payload) { + console.log('registerSubscriptionCallback payload', payload); + console.log('registerSubscriptionCallback header', header); + handleSubscriptionMessage(payload); + }); + }; + const handleNotification = (payload, type) => { console.log('handleNotification', payload, type); const notification = { @@ -266,6 +275,10 @@ function JKDashboardMain() { } }; + const handleSubscriptionMessage = payload => { + + } + useScript(`${process.env.REACT_APP_CLIENT_BASE_URL}/client_scripts`, initJKScripts); return ( diff --git a/jam-ui/src/components/jamtracks/JKCreateCustomMix.js b/jam-ui/src/components/jamtracks/JKCreateCustomMix.js index 08e84a8af..ebce7e0a8 100644 --- a/jam-ui/src/components/jamtracks/JKCreateCustomMix.js +++ b/jam-ui/src/components/jamtracks/JKCreateCustomMix.js @@ -1,19 +1,30 @@ import React, { useState, useEffect, useRef } from 'react'; import { Table, Row, Col, Input, Button } from 'reactstrap'; import Select from 'react-select'; -import { useForm, Controller } from 'react-hook-form'; -import { createMyMixdown, addMixdown } from '../../store/features/jamTrackSlice'; +import { useForm, Controller, set } from 'react-hook-form'; +import { + createMyMixdown, + enqueueMyMixdown, + addWatchedMixdown, + removeWatchedMixdown +} from '../../store/features/jamTrackSlice'; import { useDispatch, useSelector } from 'react-redux'; import { Scrollbar } from 'react-scrollbars-custom'; +import { SAMPLE_RATE } from '../../helpers/jamTracks'; +import JKModalDialog from '../common/JKModalDialog'; +import { createAlert } from '../../helpers/rest'; +import { useAuth } from '../../context/UserAuth'; const JKCreateCustomMix = () => { const MAX_MIXDOWNS = 5; const [tracks, setTracks] = useState([]); - const [mixdowns, setMixdowns] = useState([]); const [selectedTracks, setSelectedTracks] = useState([]); + const [showQueueTime, setShowQueueTime] = useState(false); + const [enqueueTimeMessage, setEnqueueTimeMessage] = useState(''); const dispatch = useDispatch(); const scrollbar = useRef(); + const { currentUser} = useAuth(); const TEMPO_OPTIONS = [ { value: '0', label: 'Original tempo' }, @@ -68,7 +79,12 @@ const JKCreateCustomMix = () => { ]; const jamTrack = useSelector(state => state.jamTrack.jamTrack); + const mixdowns = useSelector(state => state.jamTrack.mixdowns); const newMixdownLoadingStatus = useSelector(state => state.jamTrack.newMixdownLoadingStatus); + const awaitingMixdown = useSelector(state => state.jamTrack.awaitingMixdown); + const enqueuedMixdown = useSelector(state => state.jamTrack.enqueuedMixdown); + const enqueuedMixdowns = useSelector(state => state.jamTrack.enqueuedMixdowns); + const watchedMixdowns = useSelector(state => state.jamTrack.watchedMixdowns); const { control, @@ -114,11 +130,16 @@ const JKCreateCustomMix = () => { const mixData = { jamTrackID: jamTrack.id, name: data.mixName, - settings: { speed: parseInt(data.tempo.value), pitch: parseInt(data.pitch.value), 'count-in': countIn, tracks: _tracks } + settings: { + speed: parseInt(data.tempo.value), + pitch: parseInt(data.pitch.value), + 'count-in': countIn, + tracks: _tracks + } }; - const tempMixdown = {...mixData, id: 'temp', jam_track_id: jamTrack.id}; - dispatch(addMixdown(tempMixdown)); + //const tempMixdown = { ...mixData, id: 'temp', jam_track_id: jamTrack.id }; + //dispatch(addMixdown(tempMixdown)); dispatch(createMyMixdown(mixData)); }; @@ -137,23 +158,133 @@ const JKCreateCustomMix = () => { useEffect(() => { if (jamTrack) { setTracks(jamTrack.tracks.filter(track => track.track_type === 'Track' || track.track_type === 'Click')); - setMixdowns(jamTrack.mixdowns); } + //reset watched mixdowns on unload + return () => { + watchedMixdowns.forEach(subscription => { + window.JK.SubscriptionUtils.unsubscribe(subscription.type, subscription.id); + }); + }; }, [jamTrack]); useEffect(() => { - if (jamTrack) { - if(newMixdownLoadingStatus === 'succeeded') { - setValue('mixName', ''); - setValue('tempo', TEMPO_OPTIONS[0]); - setValue('pitch', PITCH_OPTIONS[0]); - setValue('mixdownTracks', []); - setSelectedTracks([]); - setMixdowns(jamTrack.mixdowns); - } + if (newMixdownLoadingStatus === 'succeeded') { + setValue('mixName', ''); + setValue('tempo', TEMPO_OPTIONS[0]); + setValue('pitch', PITCH_OPTIONS[0]); + setValue('mixdownTracks', []); + setSelectedTracks([]); } }, [newMixdownLoadingStatus]); + useEffect(() => { + if (awaitingMixdown) { + //enqueue the mixdown + console.log('Enqueueing mixdown', awaitingMixdown); + const options = { id: awaitingMixdown.id, file_type: 'mp3', encrypt_type: null, sample_rate: SAMPLE_RATE }; + dispatch(enqueueMyMixdown(options)); + } + }, [awaitingMixdown]); + + useEffect(() => { + if (enqueuedMixdown) { + showEstimatedTime(); + manageWatchedMixdowns(); + } + }, [enqueuedMixdown]); + + const showEstimatedTime = () => { + console.log('Enqueued mixdown', enqueuedMixdown); + const time = enqueuedMixdown.queue_time; + + if (time === 0) { + setEnqueueTimeMessage('Your custom mix will take about 1 minute to be created.'); + } else { + const guess = Math.ceil(time / 60.0); + if (guess === 1) { + setEnqueueTimeMessage('Your custom mix will take about 1 minute to be created.'); + } else { + setEnqueueTimeMessage(`Your custom mix will take about ${guess} minutes to be created.`); + } + } + setShowQueueTime(true); + }; + + const manageWatchedMixdowns = () => { + console.log('Managing watched mixdowns'); + mixdowns.forEach(mixdown => { + if (mixdown.oggPackage) { + if (mixdown.oggPackage.signing_state === 'SIGNED') { + console.log('unsubscribing to mixdown', mixdown); + unsubscribe(mixdown.oggPackage); + } else { + console.log('subscribing to mixdown', mixdown); + subscribe(mixdown.oggPackage); + } + } + }); + }; + + const subscriptionKey = mixdown_package => { + return `mixdown-${mixdown_package.id}`; + }; + + const subscribe = mixdown_package => { + const key = subscriptionKey(mixdown_package); + console.log('watchedMixdowns', watchedMixdowns); + if (!watchedMixdowns[key]) { + window.JK.SubscriptionUtils.subscribe('mixdown', mixdown_package.id).on( + window.JK.EVENTS.SUBSCRIBE_NOTIFICATION, + onMixdownSubscriptionEvent + ); + dispatch(addWatchedMixdown({ type: 'mixdown', id: mixdown_package.id })); + } + }; + + const unsubscribe = mixdown_package => { + const key = subscriptionKey(mixdown_package); + if (watchedMixdowns[key]) { + window.JK.SubscriptionUtils.unsubscribe('mixdown', mixdown_package.id); + dispatch(removeWatchedMixdown({ type: 'mixdown', id: mixdown_package.id })); + } + }; + + const onMixdownSubscriptionEvent = (e, data) => { + console.log("JamTrackStore: subscription notification received: type:" + data.type, data) + const mixdown_package_id = data.id; + mixdowns.forEach(mixdown => { + const mixdown_package = mixdown.packages.find(p => p.id === mixdown_package_id); + if (mixdown_package) { + mixdown_package.signing_state = data.body.signing_state + mixdown_package.packaging_steps = data.body.packaging_steps + mixdown_package.current_packaging_step = data.body.current_packaging_step + console.log("updated package with subscription notification event") + + if(mixdown_package.signing_state === 'SIGNING_TIMEOUT' || mixdown_package.signing_state === 'QUEUED_TIMEOUT' || mixdown_package.signing_state === 'QUIET_TIMEOUT' || mixdown_package.signing_state === 'ERROR'){ + reportError(mixdown) + } + } + }) + } + + const reportError = (mixdown) => { + const enqueued = enqueuedMixdowns[mixdown?.id] + if (!enqueued || enqueued.marked) { + return + } + enqueued.marked = true + const data = { + value: 1, + user_id: currentUser.id, + user_name: currentUser.name, + result: `signing state: ${mixdown.oggPackage?.signing_state}, client state: ${mixdown.client_state}`, + mixdown: mixdown.id, + package: mixdown.oggPackage?.id, + detail: mixdown.oggPackage?.error_reason + } + createAlert(`Mixdown Sync failed for ${currentUser.name}`, data) + } + const trackName = track => { if (track.track_type === 'Track' || track.track_type === 'Click') { if (track.track_type === 'Click') { @@ -180,30 +311,34 @@ const JKCreateCustomMix = () => {
- - - - - - - - - - - {tracks && - tracks.map((track, index) => ( - - - - - ))} - - -
Tracks {tracks.length > 0 && <>({tracks.length})}Mute
- {trackName(track)} - - -
+ + + + + + + + + + {tracks && + tracks.map((track, index) => ( + + + + + ))} + +
Tracks {tracks.length > 0 && <>({tracks.length})}Mute
+ {trackName(track)} + + +
{ rules={{ required: 'Select at least one track to create a mix' }} - render={({ field }) => } + render={({ field }) => } /> {errors.mixdownTracks && (
@@ -222,7 +357,9 @@ const JKCreateCustomMix = () => { - Tempo + + Tempo + { - Pitch + + Pitch + { - Mix Name + + Mix Name + { - - + setShowQueueTime(!showQueueTime)} + title="Mixdown Queued" + showFooter={true} + > +
+

{enqueueTimeMessage}

+
+
); }; diff --git a/jam-ui/src/components/jamtracks/JKJamTrack.js b/jam-ui/src/components/jamtracks/JKJamTrack.js index 2d8214f09..10bf9cb44 100644 --- a/jam-ui/src/components/jamtracks/JKJamTrack.js +++ b/jam-ui/src/components/jamtracks/JKJamTrack.js @@ -8,14 +8,13 @@ import { getUserDetail, postUserEvent, userOpenedJamTrackWebPlayer } from '../.. import JKJamTrackPlayer from './JKJamTrackPlayer'; import JKMyJamTrackMixes from './JKMyJamTrackMixes'; import JKCreateCustomMix from './JKCreateCustomMix'; +import JKJamTrackResourceLinks from './JKJamTrackResourceLinks'; import { useAuth } from '../../context/UserAuth'; import { fetchJamTrack } from '../../store/features/jamTrackSlice'; import { useDispatch, useSelector } from 'react-redux'; const JKJamTrack = () => { - console.log('JKJamTrack rendering'); - const { t } = useTranslation('jamtracks'); const { greaterThan } = useResponsive(); const { id } = useParams(); @@ -25,7 +24,7 @@ const JKJamTrack = () => { const dispatch = useDispatch(); const jamTrack = useSelector(state => state.jamTrack.jamTrack); - const jamTrackLoadingStatus = useSelector(state => state.jamTrack.status); + const jamTrackLoadingStatus = useSelector(state => state.jamTrack.jamTrackLoadingStatus); const fetchJamTrackRecord = () => { dispatch(fetchJamTrack({ id })); @@ -62,7 +61,7 @@ const JKJamTrack = () => { <> {jamTrackLoadingStatus === 'loading' || jamTrackLoadingStatus == 'idel' ? (
Loading...
- ) : Object.keys(jamTrack).length ? ( + ) : jamTrack ? ( @@ -84,41 +83,7 @@ const JKJamTrack = () => { -
- - {t('jamtrack.help_resources.using_overview.description')} -
-
- - {t('jamtrack.help_resources.using_mac_windows.description')} -
-
- - {t('jamtrack.help_resources.jamtracks_home.description')} -
-
- - {t('jamtrack.help_resources.see_more.description')} -
+
diff --git a/jam-ui/src/components/jamtracks/JKJamTrackPlayer.js b/jam-ui/src/components/jamtracks/JKJamTrackPlayer.js index 244ab30d1..0a75b3beb 100644 --- a/jam-ui/src/components/jamtracks/JKJamTrackPlayer.js +++ b/jam-ui/src/components/jamtracks/JKJamTrackPlayer.js @@ -5,7 +5,7 @@ import FingerprintJS from '@fingerprintjs/fingerprintjs'; import { useSelector, useDispatch } from 'react-redux'; import JKModalDialog from '../common/JKModalDialog'; import { enqueueMyMixdown } from '../../store/features/jamTrackSlice'; -import { set } from 'react-hook-form'; +import { SAMPLE_RATE } from '../../helpers/jamTracks'; const JKJamTrackPlayer = () => { const [options, setOptions] = useState([]); @@ -15,7 +15,6 @@ const JKJamTrackPlayer = () => { const audioRef = useRef(null); const jamTrack = useSelector(state => state.jamTrack.jamTrack); const mixdownsLoadingStatus = useSelector(state => state.jamTrack.mixdownsLoadingStatus); - const SAMPLE_RATE = 48; const [retryMessage, setRetryMessage] = useState(''); const [showRetry, setShowRetry] = useState(false); const [retryDownload, setRetryDownload] = useState(false); @@ -24,7 +23,7 @@ const JKJamTrackPlayer = () => { useEffect(() => { if (jamTrack) { - const opts = jamTrack.mixdowns.filter(mix => mix.id !== 'temp').map(mix => ({ value: mix.id, label: mix.name })); + const opts = jamTrack.mixdowns.map(mix => ({ value: mix.id, label: mix.name })); opts.unshift({ value: 'original', label: 'Original' }); setOptions(opts); if (jamTrack.last_mixdown_id) { @@ -55,7 +54,7 @@ const JKJamTrackPlayer = () => { return; } - console.log('selectedOption', selectedOption); + if (selectedOption.value === 'original') { const audioUrl = getOriginalTrackUrl(); setAudioUrl(audioUrl); @@ -64,19 +63,17 @@ const JKJamTrackPlayer = () => { } } else { //it's a mixdown - //see if there is a myPackage avaialble. if it is, it means the mixdown is ready - //if not, it means the mixdown is still being processed - - const myPackage = jamTrack.mixdowns - .find(mix => mix.id === selectedOption.value) - ?.packages.find(p => p.file_type === 'mp3' && p.encrypt_type === null && p.sample_rate === SAMPLE_RATE); - - console.log('_DEBUG_ myPackage', myPackage); - + console.log('_selectedOption', jamTrack); let retry = false; - if (myPackage) { - //let see if the mixdown is signed - switch (myPackage.signing_state) { + if (jamTrack.mp3Package && jamTrack.mp3Package.signing_state) { + // SIGNED - the package is ready to be downloaded + // ERROR - the package was built unsuccessfully + // SIGNING_TIMEOUT - the package was kicked off to be signed, but it seems to have hung + // SIGNING - the package is currently signing + // QUEUED_TIMEOUT - the package signing job (JamTrackBuilder) was queued, but never executed + // QUEUED - the package is queued to sign + // QUIET - the jam_track_right exists, but no job has been kicked off; a job needs to be enqueued + switch (jamTrack.mp3Package.signing_state) { case 'QUIET_TIMEOUT': setRetryMessage('Custom mix never got created. Retry?'); retry = true; @@ -86,13 +83,17 @@ const JKJamTrackPlayer = () => { retry = true; break; case 'SIGNING_TIMEOUT': - setRetryMessage('Custom mix took took long to build. Retry?'); + setRetryMessage('Custom mix took long to build. Retry?'); retry = true; break; case 'ERROR': setRetryMessage('Custom mix failed to build. Retry?'); retry = true; break; + case 'QUIET': + setRetryMessage('Custom mix never got created. Retry?'); + retry = true; + break; default: break; } @@ -102,6 +103,7 @@ const JKJamTrackPlayer = () => { setAudioUrl(null); } + if (retry) { setShowRetry(true); return; @@ -120,6 +122,7 @@ const JKJamTrackPlayer = () => { useEffect(() => { if (retryDownload && selectedOption) { const options = { id: selectedOption.value, file_type: 'mp3', encrypt_type: null, sample_rate: SAMPLE_RATE }; + console.log('enqueueMyMixdown', options); dispatch(enqueueMyMixdown(options)); } }, [retryDownload]); diff --git a/jam-ui/src/components/jamtracks/JKJamTrackResourceLinks.js b/jam-ui/src/components/jamtracks/JKJamTrackResourceLinks.js new file mode 100644 index 000000000..e075f2c0e --- /dev/null +++ b/jam-ui/src/components/jamtracks/JKJamTrackResourceLinks.js @@ -0,0 +1,49 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +const JKJamTrackResourceLinks = ({jamTrack}) => { + const { t } = useTranslation('jamtracks'); + return ( + <> +
+ + {t('jamtrack.help_resources.using_overview.description')} +
+
+ + {t('jamtrack.help_resources.using_mac_windows.description')} +
+
+ + {t('jamtrack.help_resources.jamtracks_home.description')} +
+
+ + {t('jamtrack.help_resources.see_more.description')} +
+ + ); +}; + +export default JKJamTrackResourceLinks; diff --git a/jam-ui/src/components/jamtracks/JKMyJamTrackMixes.js b/jam-ui/src/components/jamtracks/JKMyJamTrackMixes.js index 627886aa3..564b8982f 100644 --- a/jam-ui/src/components/jamtracks/JKMyJamTrackMixes.js +++ b/jam-ui/src/components/jamtracks/JKMyJamTrackMixes.js @@ -6,30 +6,13 @@ import { useDispatch, useSelector } from 'react-redux'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; const JKMyJamTrackMixes = () => { - const [mixes, setMixes] = useState([]); const fpPromise = FingerprintJS.load(); const dispatch = useDispatch(); const jamTrack = useSelector(state => state.jamTrack.jamTrack); + const mixdowns = useSelector(state => state.jamTrack.mixdowns); const mixdownsLoadingStatus = useSelector(state => state.jamTrack.mixdownsLoadingStatus); const deleteMixdownStatus = useSelector(state => state.jamTrack.deleteMixdownStatus); - const tempMixdownLoadingStatus = useSelector(state => state.jamTrack.tempMixdownLoadingStatus); - const buildRetries = useSelector(state => state.jamTrack.buildRetries); - - useEffect(() => { - if (!jamTrack) { - return; - } - if (mixdownsLoadingStatus === 'succeeded') { - setMixes(jamTrack.mixdowns.filter(m => m.id !== 'temp')); - } - }, [mixdownsLoadingStatus]); - - useEffect(() => { - if (tempMixdownLoadingStatus === 'succeeded') { - setMixes(jamTrack.mixdowns); - } - }, [tempMixdownLoadingStatus]); const downloadJamTrack = async () => { console.log('Downloading JamTrack'); @@ -47,7 +30,7 @@ const JKMyJamTrackMixes = () => { const downloadMix = async mixId => { console.log('Download mixdown'); - const mixdown = mixes.find(m => m.id === mixId); + const mixdown = mixdowns.find(m => m.id === mixId); const mixdownPackage = mixdown.packages.find(p => p.file_type === 'mp3'); if (mixdownPackage?.signing_state == 'SIGNED') { const fp = await fpPromise; @@ -56,7 +39,7 @@ const JKMyJamTrackMixes = () => { mixdown.id }/download.mp3?file_type=mp3&sample_rate=48&download=1&mark=${result.visitorId}`; openDownload(src); - }else{ + } else { console.log('Mixdown not signed'); } }; @@ -75,10 +58,17 @@ const JKMyJamTrackMixes = () => { } }; - const isMixdownBuilding = mix => { - const retry = buildRetries.find(retry => retry.mixdownId === mix.id); - return mix.id === 'temp' || (retry && ['queued', 'enqueuing'].includes(retry.state)) - } + const mixdownPackage = mixdown => { + if (!mixdown.packages || mixdown.packages.length === 0) { + return null; + } + return mixdown.packages[0]; + }; + + const isMixdownPackageReady = mixdown => { + const pkg = mixdownPackage(mixdown); + return pkg && pkg.signing_state === 'SIGNED'; + }; return ( <> @@ -102,25 +92,36 @@ const JKMyJamTrackMixes = () => { - {mixes.map(mix => ( - - {mix.name} + {mixdowns.map(mixdown => ( + + + {mixdown.name}
+ {mixdown.id}
+ pkg-{mixdownPackage(mixdown)?.signing_state} + - {isMixdownBuilding(mix) ? ( - - ) : ( + + {isMixdownPackageReady(mixdown) ? ( <> - downloadMix(mix.id)} style={{ cursor: 'pointer' }}> + downloadMix(mixdown.id)} style={{ cursor: 'pointer' }}> deleteMix(mix.id)} + onClick={() => deleteMix(mixdown.id)} disabled={deleteMixdownStatus === 'loading'} style={{ cursor: 'pointer' }} > + ) : ( + <> + {mixdown.signing_state === 'QUEUED' || mixdown.signing_state === 'SIGNING' ? ( + + ) : ( + + )} + )} diff --git a/jam-ui/src/helpers/jamTracks.js b/jam-ui/src/helpers/jamTracks.js new file mode 100644 index 000000000..7f69ab064 --- /dev/null +++ b/jam-ui/src/helpers/jamTracks.js @@ -0,0 +1 @@ +export const SAMPLE_RATE = 48; \ No newline at end of file diff --git a/jam-ui/src/helpers/rest.js b/jam-ui/src/helpers/rest.js index 8c57e8c79..e67db40cd 100644 --- a/jam-ui/src/helpers/rest.js +++ b/jam-ui/src/helpers/rest.js @@ -1,4 +1,3 @@ -import { error } from 'is_js'; import apiFetch from './apiFetch'; export const getMusicians = page => { @@ -622,4 +621,15 @@ export const deleteAvatar = id => { .then(response => resolve(response)) .catch(error => reject(error)); }); -} \ No newline at end of file +} + +export const createAlert = (subject, data) => { + return new Promise((resolve, reject) => { + apiFetch(`/alerts`, { + method: 'POST', + body: JSON.stringify({subject, data}) + }) + .then(response => resolve(response)) + .catch(error => reject(error)); + }); +}; \ No newline at end of file diff --git a/jam-ui/src/store/features/jamTrackSlice.js b/jam-ui/src/store/features/jamTrackSlice.js index 6c623304a..94d2b159c 100644 --- a/jam-ui/src/store/features/jamTrackSlice.js +++ b/jam-ui/src/store/features/jamTrackSlice.js @@ -1,15 +1,19 @@ import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; import { deleteMixdown, getJamTrack, createMixdown, enqueueMixdown } from '../../helpers/rest'; +import { SAMPLE_RATE } from '../../helpers/jamTracks'; const initialState = { - jamTrack: {}, + jamTrack: null, + mixdowns: [], + awaitingMixdown: null, + enqueuedMixdown: null, + enqueuedMixdowns: [], + watchedMixdowns: [], jamTrackLoadingStatus: 'idle', mixdownsLoadingStatus: 'idle', deleteMixdownStatus: 'idle', newMixdownLoadingStatus: 'idle', tempMixdownLoadingStatus: 'idle', - enqueueLoadingStatus: 'idle', - buildRetries: [], error: null }; @@ -24,7 +28,6 @@ export const createMyMixdown = createAsyncThunk('jamTracks/createMixdown', async }); export const removeMixdown = createAsyncThunk('jamTracks/removeMixdown', async (options, thunkAPI) => { - console.log('removeMixdown', options); const { id } = options; const response = await deleteMixdown(id); return { id }; @@ -35,6 +38,10 @@ export const enqueueMyMixdown = createAsyncThunk('jamTracks/enqueueMixdown', asy return response.json(); }); + + + + export const jamTrackSlice = createSlice({ name: 'jamTrack', initialState, @@ -46,6 +53,26 @@ export const jamTrackSlice = createSlice({ state.jamTrack.mixdowns = [...jamTrack.mixdowns, payload]; state.tempMixdownLoadingStatus = 'succeeded'; } + }, + addWatchedMixdown: (state, action) => { + const payload = action.payload; + state.watchedMixdowns = [...state.watchedMixdowns, payload]; + }, + removeWatchedMixdown: (state, action) => { + const payload = action.payload; + state.watchedMixdowns = state.watchedMixdowns.filter(mix => mix.id !== payload.id); + }, + updateMixdown: (state, action) => { + const payload = action.payload; + const jamTrack = state.jamTrack; + if (jamTrack) { + state.jamTrack.mixdowns = jamTrack.mixdowns.map(mix => { + if (mix.id === payload.id) { + return payload; + } + return mix; + }); + } } }, extraReducers: builder => { @@ -57,23 +84,26 @@ export const jamTrackSlice = createSlice({ .addCase(fetchJamTrack.fulfilled, (state, action) => { state.jamTrack = action.payload; state.jamTrackLoadingStatus = 'succeeded'; - if (action.payload.mixdowns) { + state.mixdowns = action.payload.mixdowns; + assignPackages(state); state.mixdownsLoadingStatus = 'succeeded'; } }) .addCase(fetchJamTrack.rejected, (state, action) => { - state.status = 'failed'; state.jamTrackLoadingStatus = 'failed'; + state.jamTrack = null; state.mixdownsLoadingStatus = 'failed'; + state.mixdowns = []; state.error = action.error.message; }) .addCase(createMyMixdown.pending, (state, action) => { state.newMixdownLoadingStatus = 'loading'; - state.mixdownsLoadingStatus = 'loading'; + state.tempMixdownLoadingStatus = 'loading'; }) .addCase(createMyMixdown.fulfilled, (state, action) => { - state.jamTrack.mixdowns = [...state.jamTrack.mixdowns, action.payload]; + state.mixdowns = [...state.mixdowns, action.payload]; + state.awaitingMixdown = action.payload; state.newMixdownLoadingStatus = 'succeeded'; state.mixdownsLoadingStatus = 'succeeded'; state.tempMixdownLoadingStatus = 'idle'; @@ -88,9 +118,7 @@ export const jamTrackSlice = createSlice({ state.deleteMixdownStatus = 'loading'; }) .addCase(removeMixdown.fulfilled, (state, action) => { - console.log('mixdown removed', action.payload); - const mixdowns = state.jamTrack.mixdowns.filter(mix => mix.id !== action.payload.id); - state.jamTrack.mixdowns = mixdowns; + const mixdowns = state.mixdowns.filter(mix => mix.id !== action.payload.id); state.mixdowns = mixdowns; state.mixdownsLoadingStatus = 'succeeded'; state.deleteMixdownStatus = 'succeeded'; @@ -100,47 +128,36 @@ export const jamTrackSlice = createSlice({ state.mixdownsLoadingStatus = 'failed'; state.deleteMixdownStatus = 'failed'; }) - .addCase(enqueueMyMixdown.pending, (state, action) => { - const estimate = { mixdownId: action.meta.arg.id, state: 'enqueuing' }; - if (!state.buildRetries.find(estimate => estimate.mixdownId === action.meta.arg.id)) { - state.buildRetries = [...state.buildRetries, estimate]; - } else { - state.buildRetries = state.buildRetries.map(estimate => { - if (estimate.mixdownId === action.meta.arg.id) { - return { ...estimate, state: 'enqueuing' }; - } - return estimate; - }); - } - }) .addCase(enqueueMyMixdown.fulfilled, (state, action) => { - const estimate = { mixdownId: action.payload.id, time: action.payload.queue_time, state: 'queued' }; - if (!state.buildRetries.find(estimate => estimate.mixdownId === action.payload.id)) { - state.buildRetries = [...state.buildRetries, estimate]; - } else { - state.buildRetries = state.buildRetries.map(estimate => { - if (estimate.mixdownId === action.payload.id) { - return { ...estimate, ...action.payload, state: 'queued' }; - } - return estimate; - }); - } + console.log('enqueueMyMixdown.fulfilled', action.payload); + const enqueue = { queue_time: action.payload.queue_time, signing_state: action.payload.signing_state }; + state.enqueuedMixdown = enqueue; + state.enqueuedMixdowns = [...state.enqueuedMixdowns, enqueue]; + state.mixdowns = state.mixdowns.map(mix => { + if (mix.id === action.payload.jam_track_mixdown_id) { + return { ...mix, ...enqueue }; + } + return mix; + }); + assignPackages(state); }) - .addCase(enqueueMyMixdown.rejected, (state, action) => { - const estimate = { mixdownId: action.meta.arg.id, state: 'failed' }; - if (!state.buildRetries.find(estimate => estimate.mixdownId === action.meta.arg.id)) { - state.buildRetries = [...state.buildRetries, estimate]; - } else { - state.buildRetries = state.buildRetries.map(estimate => { - if (estimate.mixdownId === action.meta.arg.id) { - return { ...estimate, state: 'failed' }; - } - return estimate; - }); - } - }); + } }); -export const { addMixdown } = jamTrackSlice.actions; +//help functions +const pickMp3Package = (mixdown) => { + return mixdown.packages.find(p => p.file_type === 'mp3' && p.encrypt_type === null && p.sample_rate === SAMPLE_RATE); +}; + +const pickOggPackage = (mixdown) => { + return mixdown.packages.find(p => p.file_type === 'ogg' && p.encrypt_type === null && p.sample_rate === SAMPLE_RATE); +}; + +const assignPackages = (state) => { + state.jamTrack.mp3Package = state.mixdowns.map(pickMp3Package).filter(p => p); + state.jamTrack.oggPackage = state.mixdowns.map(pickOggPackage).filter(p => p); +}; + +export const { addMixdown, addWatchedMixdown, removeWatchedMixdown } = jamTrackSlice.actions; export default jamTrackSlice.reducer; diff --git a/web/app/assets/javascripts/JamServer.js b/web/app/assets/javascripts/JamServer.js index 91821766b..8b717e2f5 100644 --- a/web/app/assets/javascripts/JamServer.js +++ b/web/app/assets/javascripts/JamServer.js @@ -627,6 +627,7 @@ } server.registerMessageCallback = function (messageType, callback) { + console.log("_DEBUG_ jamserver server.registerMessageCallback", messageType, callback) if (server.dispatchTable[messageType] === undefined) { server.dispatchTable[messageType] = []; } @@ -818,6 +819,8 @@ var jsMessage = JSON.stringify(message); + console.log("server.send(" + jsMessage + ")"); + if( isLatencyTester() && (message.type == context.JK.MessageType.HEARTBEAT || message.type == context.JK.MessageType.PEER_MESSAGE)) { logger.info("latency-tester: server.send(" + jsMessage + ")") } diff --git a/web/app/assets/javascripts/modern/JamServer_copy.js b/web/app/assets/javascripts/modern/JamServer_copy.js index bad59e74f..0ab20fd77 100644 --- a/web/app/assets/javascripts/modern/JamServer_copy.js +++ b/web/app/assets/javascripts/modern/JamServer_copy.js @@ -607,6 +607,7 @@ } server.registerMessageCallback = function (messageType, callback) { + console.log("_DEBUG_ jamserver_copy server.registerMessageCallback", messageType, callback) if (server.dispatchTable[messageType] === undefined) { server.dispatchTable[messageType] = []; } diff --git a/web/app/assets/javascripts/subscription_utils.js.coffee b/web/app/assets/javascripts/subscription_utils.js.coffee index b9b3e7823..456afedf4 100644 --- a/web/app/assets/javascripts/subscription_utils.js.coffee +++ b/web/app/assets/javascripts/subscription_utils.js.coffee @@ -72,6 +72,7 @@ class SubscriptionUtils $server.on(@events.CONNECTION_DOWN, this.onConnectionDown) onSubscriptionMessage: (header, payload) => + console.log("onSubscriptionMessage", payload, header) key = this.genKey(payload.type, payload.id) watch = @subscriptions[key] diff --git a/web/app/controllers/api_jam_track_mixdowns_controller.rb b/web/app/controllers/api_jam_track_mixdowns_controller.rb index 9efd1ca5d..53b121b0f 100644 --- a/web/app/controllers/api_jam_track_mixdowns_controller.rb +++ b/web/app/controllers/api_jam_track_mixdowns_controller.rb @@ -118,7 +118,6 @@ class ApiJamTrackMixdownsController < ApiController end def enqueue - debugger if @jam_track_right.valid? begin