wip jamtrack page creating and playing custom jamtracks
This commit is contained in:
parent
08fafbf2de
commit
c3563a9197
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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 = () => {
|
|||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<Row>
|
||||
<Col>
|
||||
<Scrollbar ref={scrollbar} style={{ width: '100%', height: 300 }} mobileNative={true}>
|
||||
<Table striped bordered className="fs--1 mb-0">
|
||||
<thead className="bg-200 text-900">
|
||||
<tr>
|
||||
<th>Tracks {tracks.length > 0 && <>({tracks.length})</>}</th>
|
||||
<th className="text-center">Mute</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{tracks &&
|
||||
tracks.map((track, index) => (
|
||||
<tr key={index}>
|
||||
<td>
|
||||
<span>{trackName(track)}</span>
|
||||
</td>
|
||||
<td className="text-center">
|
||||
<input type="checkbox" value={track.id} onChange={toggleTrack} checked={ selectedTracks.includes(track.id)} disabled={hasExceededMax} />
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
|
||||
</tbody>
|
||||
</Table>
|
||||
<Scrollbar ref={scrollbar} style={{ width: '100%', height: 300 }} mobileNative={true}>
|
||||
<Table striped bordered className="fs--1 mb-0">
|
||||
<thead className="bg-200 text-900">
|
||||
<tr>
|
||||
<th>Tracks {tracks.length > 0 && <>({tracks.length})</>}</th>
|
||||
<th className="text-center">Mute</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{tracks &&
|
||||
tracks.map((track, index) => (
|
||||
<tr key={index}>
|
||||
<td>
|
||||
<span>{trackName(track)}</span>
|
||||
</td>
|
||||
<td className="text-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
value={track.id}
|
||||
onChange={toggleTrack}
|
||||
checked={selectedTracks.includes(track.id)}
|
||||
disabled={hasExceededMax}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</Table>
|
||||
</Scrollbar>
|
||||
<Controller
|
||||
name="mixdownTracks"
|
||||
|
|
@ -211,7 +346,7 @@ const JKCreateCustomMix = () => {
|
|||
rules={{
|
||||
required: 'Select at least one track to create a mix'
|
||||
}}
|
||||
render={({ field }) => <Input type='hidden' {...field} />}
|
||||
render={({ field }) => <Input type="hidden" {...field} />}
|
||||
/>
|
||||
{errors.mixdownTracks && (
|
||||
<div className="text-danger">
|
||||
|
|
@ -222,7 +357,9 @@ const JKCreateCustomMix = () => {
|
|||
</Row>
|
||||
|
||||
<Row className="mb-3 mt-3">
|
||||
<Col sm={6} md={4} lg={3}>Tempo</Col>
|
||||
<Col sm={6} md={4} lg={3}>
|
||||
Tempo
|
||||
</Col>
|
||||
<Col>
|
||||
<Controller
|
||||
name="tempo"
|
||||
|
|
@ -232,7 +369,9 @@ const JKCreateCustomMix = () => {
|
|||
</Col>
|
||||
</Row>
|
||||
<Row className="mb-3">
|
||||
<Col sm={6} md={4} lg={3}>Pitch</Col>
|
||||
<Col sm={6} md={4} lg={3}>
|
||||
Pitch
|
||||
</Col>
|
||||
<Col>
|
||||
<Controller
|
||||
name="pitch"
|
||||
|
|
@ -242,7 +381,9 @@ const JKCreateCustomMix = () => {
|
|||
</Col>
|
||||
</Row>
|
||||
<Row className="mb-3">
|
||||
<Col sm={6} md={4} lg={3}>Mix Name</Col>
|
||||
<Col sm={6} md={4} lg={3}>
|
||||
Mix Name
|
||||
</Col>
|
||||
<Col>
|
||||
<Controller
|
||||
name="mixName"
|
||||
|
|
@ -260,13 +401,23 @@ const JKCreateCustomMix = () => {
|
|||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col className='d-flex justify-content-end'>
|
||||
<Button color="primary" disabled={newMixdownLoadingStatus === 'loading' || hasExceededMax }>
|
||||
<Col className="d-flex justify-content-end">
|
||||
<Button color="primary" disabled={newMixdownLoadingStatus === 'loading' || hasExceededMax}>
|
||||
{newMixdownLoadingStatus === 'loading' ? 'Creating Mix...' : 'Create Mix'}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</form>
|
||||
<JKModalDialog
|
||||
show={showQueueTime}
|
||||
onToggle={() => setShowQueueTime(!showQueueTime)}
|
||||
title="Mixdown Queued"
|
||||
showFooter={true}
|
||||
>
|
||||
<div className="d-flex flex-column">
|
||||
<p>{enqueueTimeMessage}</p>
|
||||
</div>
|
||||
</JKModalDialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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' ? (
|
||||
<div>Loading...</div>
|
||||
) : Object.keys(jamTrack).length ? (
|
||||
) : jamTrack ? (
|
||||
<Row>
|
||||
<Col sm={12} md={4}>
|
||||
<Card className="mx-auto mb-4">
|
||||
|
|
@ -84,41 +83,7 @@ const JKJamTrack = () => {
|
|||
<Card className="mx-auto">
|
||||
<FalconCardHeader title={t('jamtrack.help_resources.title')} titleClass="font-weight-semi-bold" />
|
||||
<CardBody className="pt-3">
|
||||
<div className="mb-3">
|
||||
<div>
|
||||
<a target="_blank" href="https://jamkazam.freshdesk.com/support/solutions/articles/66000501472">
|
||||
{t('jamtrack.help_resources.using_overview.title')}
|
||||
</a>
|
||||
</div>
|
||||
{t('jamtrack.help_resources.using_overview.description')}
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<div>
|
||||
<a target="_blank" href="https://jamkazam.freshdesk.com/support/solutions/articles/66000125792">
|
||||
{t('jamtrack.help_resources.using_mac_windows.title')}
|
||||
</a>
|
||||
</div>
|
||||
{t('jamtrack.help_resources.using_mac_windows.description')}
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<div>
|
||||
<a target="_blank" href="https://www.jamkazam.com/client#/jamtrack">
|
||||
{t('jamtrack.help_resources.jamtracks_home.title')}
|
||||
</a>
|
||||
</div>
|
||||
{t('jamtrack.help_resources.jamtracks_home.description')}
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<div>
|
||||
<a target="_blank" href={`https://www.jamkazam.com/client?artist=${encodeURIComponent(
|
||||
jamTrack.original_artist
|
||||
)}#/jamtrack/search`}
|
||||
>
|
||||
{t('jamtrack.help_resources.see_more.title')}
|
||||
</a>
|
||||
</div>
|
||||
{t('jamtrack.help_resources.see_more.description')}
|
||||
</div>
|
||||
<JKJamTrackResourceLinks jamTrack={jamTrack} />
|
||||
</CardBody>
|
||||
</Card>
|
||||
</Col>
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const JKJamTrackResourceLinks = ({jamTrack}) => {
|
||||
const { t } = useTranslation('jamtracks');
|
||||
return (
|
||||
<>
|
||||
<div className="mb-3">
|
||||
<div>
|
||||
<a target="_blank" href="https://jamkazam.freshdesk.com/support/solutions/articles/66000501472">
|
||||
{t('jamtrack.help_resources.using_overview.title')}
|
||||
</a>
|
||||
</div>
|
||||
{t('jamtrack.help_resources.using_overview.description')}
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<div>
|
||||
<a target="_blank" href="https://jamkazam.freshdesk.com/support/solutions/articles/66000125792">
|
||||
{t('jamtrack.help_resources.using_mac_windows.title')}
|
||||
</a>
|
||||
</div>
|
||||
{t('jamtrack.help_resources.using_mac_windows.description')}
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<div>
|
||||
<a target="_blank" href="https://www.jamkazam.com/client#/jamtrack">
|
||||
{t('jamtrack.help_resources.jamtracks_home.title')}
|
||||
</a>
|
||||
</div>
|
||||
{t('jamtrack.help_resources.jamtracks_home.description')}
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<div>
|
||||
<a
|
||||
target="_blank"
|
||||
href={`https://www.jamkazam.com/client?artist=${encodeURIComponent(
|
||||
jamTrack.original_artist
|
||||
)}#/jamtrack/search`}
|
||||
>
|
||||
{t('jamtrack.help_resources.see_more.title')}
|
||||
</a>
|
||||
</div>
|
||||
{t('jamtrack.help_resources.see_more.description')}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default JKJamTrackResourceLinks;
|
||||
|
|
@ -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 = () => {
|
|||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{mixes.map(mix => (
|
||||
<tr key={mix.id}>
|
||||
<td>{mix.name}</td>
|
||||
{mixdowns.map(mixdown => (
|
||||
<tr key={mixdown.id}>
|
||||
<td>
|
||||
{mixdown.name} <br />
|
||||
{mixdown.id} <br />
|
||||
pkg-{mixdownPackage(mixdown)?.signing_state}
|
||||
</td>
|
||||
<td className="text-center">
|
||||
{isMixdownBuilding(mix) ? (
|
||||
<FontAwesomeIcon icon="spinner" size="lg" />
|
||||
) : (
|
||||
|
||||
{isMixdownPackageReady(mixdown) ? (
|
||||
<>
|
||||
<a onClick={() => downloadMix(mix.id)} style={{ cursor: 'pointer' }}>
|
||||
<a onClick={() => downloadMix(mixdown.id)} style={{ cursor: 'pointer' }}>
|
||||
<FontAwesomeIcon icon="download" size="lg" className="mr-3" />
|
||||
</a>
|
||||
<a
|
||||
onClick={() => deleteMix(mix.id)}
|
||||
onClick={() => deleteMix(mixdown.id)}
|
||||
disabled={deleteMixdownStatus === 'loading'}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<FontAwesomeIcon icon="trash" size="lg" />
|
||||
</a>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{mixdown.signing_state === 'QUEUED' || mixdown.signing_state === 'SIGNING' ? (
|
||||
<FontAwesomeIcon icon="spinner" size="lg" className="mr-3" />
|
||||
) : (
|
||||
<FontAwesomeIcon icon="exclamation-circle" size="lg" className="mr-3" />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
export const SAMPLE_RATE = 48;
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
import { error } from 'is_js';
|
||||
import apiFetch from './apiFetch';
|
||||
|
||||
export const getMusicians = page => {
|
||||
|
|
@ -623,3 +622,14 @@ export const deleteAvatar = id => {
|
|||
.catch(error => reject(error));
|
||||
});
|
||||
}
|
||||
|
||||
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));
|
||||
});
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 + ")")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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] = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ class ApiJamTrackMixdownsController < ApiController
|
|||
end
|
||||
|
||||
def enqueue
|
||||
debugger
|
||||
if @jam_track_right.valid?
|
||||
|
||||
begin
|
||||
|
|
|
|||
Loading…
Reference in New Issue