UI improments in JamTrack player

This commit is contained in:
Nuwan 2024-12-29 18:47:55 +05:30
parent 2d7a6db541
commit 8835455795
20 changed files with 187 additions and 84 deletions

View File

@ -263,7 +263,7 @@ describe('Browse sessions', () => {
} }
] ]
}); });
console.log('_DEBUG_ session', session); //console.log('_DEBUG_ session', session);
cy.intercept('GET', /\S+\/api\/sessions/, [session]); cy.intercept('GET', /\S+\/api\/sessions/, [session]);
cy.visit('/sessions'); cy.visit('/sessions');
cy.get('[data-testid=sessionsListTable] tbody tr').contains('YOU HAVE A FRIEND IN THIS SESSION'); cy.get('[data-testid=sessionsListTable] tbody tr').contains('YOU HAVE A FRIEND IN THIS SESSION');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g>
<g>
<g>
<path d="M83.9,2.2C80.5,3.6 78.8,4.8 76.1,7.6C71.5,12.5 70.4,16.1 70.4,26.7L70.4,34.1L40.4,34.2L10.3,34.4L10.1,39.3L10,44.3L27,44.4L44,44.6L44.6,233.8L45.8,236.6C49.2,245.1 56.1,251.6 64.5,254.2C67.6,255.2 69.5,255.2 128.2,255.2C186.9,255.2 188.8,255.2 191.9,254.2C200.3,251.6 207.1,245.1 210.6,236.6L211.8,233.8L212.4,44.6L229.4,44.4L246.4,44.3L246,34.5L216,34.3L186,34.2L185.8,25.5C185.6,18.1 185.4,16.4 184.5,14.1C182.4,8.9 177.5,4.1 172.1,2.1C169,1 168.2,1 127.9,1L86.8,1L83.9,2.2ZM170.1,11.8C172.2,12.7 174.3,15.1 175,17.5C175.3,18.5 175.5,22.7 175.5,26.8L175.5,34.2L80.5,34.2L80.5,26.8C80.5,18.6 80.9,16.4 82.9,14.1C85.5,11 83.7,11.2 128,11.1C161.1,11.1 168.8,11.2 170.1,11.8ZM201.6,138.7L201.4,233.2L200.3,235.5C198.7,238.9 195.9,241.7 192.7,243.3L189.8,244.7L66.1,244.7L63.2,243.3C59.9,241.7 57.1,238.8 55.6,235.5L54.5,233.2L54.3,138.7L54.2,44.3L201.7,44.3L201.6,138.7Z" style="fill:rgb(64,124,222);fill-rule:nonzero;"/>
<rect x="79.5" y="71.4" width="10" height="148.4" style="fill:rgb(64,124,222);fill-rule:nonzero;"/>
<path d="M123.2,145.6L123.2,219.8L133,219.4L133.2,145.3L133.3,71.3L123.3,71.3L123.2,145.6Z" style="fill:rgb(64,124,222);fill-rule:nonzero;"/>
<rect x="166.5" y="71.4" width="10" height="148.4" style="fill:rgb(64,124,222);fill-rule:nonzero;"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g>
<g>
<g>
<path d="M124.9,25.9L123.1,27.5L122.5,156.7L104.4,139.1C87.8,122.8 86.2,121.5 84.1,121.5C82.4,121.5 81.4,122 80.4,123.2C77.5,126.9 77.3,126.7 101.8,151.2C114.3,163.7 125.3,174.2 126.2,174.5C127.2,174.9 128.4,174.9 129.4,174.5C130.2,174.2 141.3,163.8 153.8,151.4C175.3,130.2 176.7,128.7 176.7,126.6C176.7,123.6 174.5,121.4 171.5,121.4C169.5,121.4 167.7,123 151.4,139.1L133.4,156.9L133.3,92.7C133.2,46.7 132.9,28.1 132.4,27.1C131.7,25.7 129.3,24.2 127.6,24.2C127.2,24.3 125.9,25.1 124.9,25.9Z" style="fill:rgb(64,124,222);fill-rule:nonzero;"/>
<path d="M11.6,147.2L10,148.8L10,227.9L13.8,231.7L127.7,231.7C213,231.7 241.9,231.5 243,230.9C246.1,229.3 246,230.3 246.1,188.6C246.1,149.6 246.1,149 244.7,147.3C242.9,145 239.5,145 237.3,147.2L235.7,148.8L235.7,221.2L20.4,221.2L20.4,185.1C20.4,149.6 20.4,149 19,147.3C17.2,145 13.8,145 11.6,147.2Z" style="fill:rgb(64,124,222);fill-rule:nonzero;"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,8 +1,7 @@
.audio-player { .audio-player {
height: 30px; height: 32px;
background: #ffffff; background: #ffffff;
//box-shadow: 0 0 20px 0 #000a;
font-family: arial; font-family: arial;
color: #1b1a1a; color: #1b1a1a;
font-size: 0.75em; font-size: 0.75em;
@ -29,7 +28,7 @@
margin-bottom: auto; margin-bottom: auto;
margin-left: 5px; margin-left: 5px;
margin-right: 5px; margin-right: 5px;
background: rgb(14, 157, 223); background: rgb(64, 124, 222);
width: 100%; width: 100%;
height: 4px; height: 4px;
cursor: pointer; cursor: pointer;
@ -42,8 +41,6 @@
transition: 0.25s; transition: 0.25s;
} }
.audio-player .controls .play-pause-button{ .audio-player .controls .play-pause-button{
background: "none"; background: "none";
border: "none"; border: "none";
@ -94,6 +91,20 @@
width: 120px; width: 120px;
} }
.audio-player .controls .download-container {
margin-right: 1px;
cursor: pointer;
position: relative;
z-index: 2;
.download-button {
background: "none";
border: "none";
cursor: "pointer";
outline: "none";
left: 0;
}
}
// .audio-player .controls .toggle-play.play { // .audio-player .controls .toggle-play.play {
// cursor: pointer; // cursor: pointer;
// position: relative; // position: relative;

View File

@ -1,9 +1,11 @@
import React, { useRef, useEffect, useState } from 'react'; import React, { useRef, useEffect, useState } from 'react';
import playIcon from '../../assets/img/icons/play-icon.svg'; import playIcon from '../../assets/img/icons/play-icon.svg';
import pauseIcon from '../../assets/img/icons/pause-icon.svg'; import pauseIcon from '../../assets/img/icons/pause-icon.svg';
import downloadIcon from '../../assets/img/icons/download-icon.svg';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import PropTypes from 'prop-types';
const JKAudioPlayer = ({ audioUrl }) => { const JKAudioPlayer = ({ audioUrl, onDownloadClick }) => {
const audioPlayer = useRef(null); const audioPlayer = useRef(null);
@ -14,7 +16,6 @@ const JKAudioPlayer = ({ audioUrl }) => {
useEffect(() => { useEffect(() => {
if (!audioUrl) return; if (!audioUrl) return;
console.log('audioUrl: ' + audioUrl) console.log('audioUrl: ' + audioUrl)
//if (audio) { stopAudio(); }
const audio = new Audio(audioUrl); const audio = new Audio(audioUrl);
setAudio(audio); setAudio(audio);
@ -60,7 +61,7 @@ const JKAudioPlayer = ({ audioUrl }) => {
} }
const togglePlayPause = (e) => { const togglePlayPause = (e) => {
if (!audio || e === "undefined") return; if (!audio) return;
if (audio.paused) { if (audio.paused) {
audio.play(); audio.play();
setIsPlaying(true); setIsPlaying(true);
@ -71,7 +72,7 @@ const JKAudioPlayer = ({ audioUrl }) => {
} }
const onClickTimeline = (e) => { const onClickTimeline = (e) => {
if (!audio || e === "undefined") return; if (!audio) return;
let timeToSeek = 0; let timeToSeek = 0;
try { try {
let timelineWidth = window.getComputedStyle(audioPlayer.current.querySelector(".timeline")).width; let timelineWidth = window.getComputedStyle(audioPlayer.current.querySelector(".timeline")).width;
@ -88,7 +89,7 @@ const JKAudioPlayer = ({ audioUrl }) => {
} }
const onVolumeSliderClick = (e) => { const onVolumeSliderClick = (e) => {
if (!audio || e === "undefined") return; if (!audio) return;
let volume = .75; let volume = .75;
try { try {
let sliderWidth = window.getComputedStyle(audioPlayer.current.querySelector(".controls .volume-slider")).width; let sliderWidth = window.getComputedStyle(audioPlayer.current.querySelector(".controls .volume-slider")).width;
@ -164,6 +165,11 @@ const JKAudioPlayer = ({ audioUrl }) => {
<div className="volume-percentage"></div> <div className="volume-percentage"></div>
</div> </div>
</div> </div>
<div className='download-container'>
<button className='download-button' onClick={onDownloadClick}>
<img src={downloadIcon} alt='download' width={30} />
</button>
</div>
</div> </div>
</div> </div>
) )
@ -171,4 +177,9 @@ const JKAudioPlayer = ({ audioUrl }) => {
} }
JKAudioPlayer.propTypes = {
audioUrl: PropTypes.string.isRequired,
onDownloadClick: PropTypes.func.isRequired
}
export default JKAudioPlayer export default JKAudioPlayer

View File

@ -9,14 +9,16 @@ import JKSigningRetryConfirmModal from './JKSigningRetryConfirmModal';
import JKSigningEstimateTimeModal from './JKSigningEstimateTimeModal'; import JKSigningEstimateTimeModal from './JKSigningEstimateTimeModal';
import { markMixdownActive } from '../../helpers/rest'; import { markMixdownActive } from '../../helpers/rest';
import JKAudioPlayer from './JKAudioPlayer'; import JKAudioPlayer from './JKAudioPlayer';
import FingerprintJS from '@fingerprintjs/fingerprintjs';
const JKJamTrackPlayer = () => { const JKJamTrackPlayer = () => {
const [options, setOptions] = useState([]); const [options, setOptions] = useState([]);
const [selectedOption, setSelectedOption] = useState(null); const [selectedOption, setSelectedOption] = useState(null);
const [audioUrl, setAudioUrl] = useState(null); const [audioUrl, setAudioUrl] = useState(null);
const audioRef = useRef(null); const audioRef = useRef(null);
const fpPromise = FingerprintJS.load();
const { jamTrack, mixdowns, getMasterAudioUrl, getMixdownAudioUrl, confirmRetryMixdownSigning, showQueueTime, setShowQueueTime, enqueueTimeMessage, retryConfirmMessage, showRetryConfirm, setShowRetryConfirm, enqueueMixdownForSigning, enqueuedMixdown, showEstimatedTime, manageWatchedMixdowns, getStemAudioUrl, trackName} = useJamTrack(); const { jamTrack, mixdowns, getMasterAudioUrl, getMixdownAudioUrl, confirmRetryMixdownSigning, showQueueTime, setShowQueueTime, enqueueTimeMessage, retryConfirmMessage, showRetryConfirm, setShowRetryConfirm, enqueueMixdownForSigning, enqueuedMixdown, showEstimatedTime, manageWatchedMixdowns, getStemAudioUrl, trackName } = useJamTrack();
useEffect(() => { useEffect(() => {
if (jamTrack && mixdowns) { if (jamTrack && mixdowns) {
@ -31,7 +33,7 @@ const JKJamTrackPlayer = () => {
setOptions(opts); setOptions(opts);
if (jamTrack.last_mixdown_id) { if (jamTrack.last_mixdown_id) {
setSelectedOption(opts.find(opt => opt.value === jamTrack.last_mixdown_id)); setSelectedOption(opts.find(opt => opt.value === jamTrack.last_mixdown_id));
}else if(jamTrack.last_stem_id){ } else if (jamTrack.last_stem_id) {
setSelectedOption(opts.find(opt => opt.value === jamTrack.last_stem_id)); setSelectedOption(opts.find(opt => opt.value === jamTrack.last_stem_id));
} else { } else {
setSelectedOption(opts[0]); setSelectedOption(opts[0]);
@ -68,7 +70,7 @@ const JKJamTrackPlayer = () => {
audioRef.current.load(); audioRef.current.load();
} }
} else if(selectedOption.data.type === 'custom-mix') { } else if (selectedOption.data.type === 'custom-mix') {
//it's a mixdown //it's a mixdown
if (!jamTrack.mp3Package || jamTrack.mp3Package?.signing_state !== 'SIGNED') { if (!jamTrack.mp3Package || jamTrack.mp3Package?.signing_state !== 'SIGNED') {
confirmRetryMixdownSigning(); confirmRetryMixdownSigning();
@ -76,7 +78,6 @@ const JKJamTrackPlayer = () => {
const activeMix = jamTrack.mixdowns.find(mix => mix.id === selectedOption.value); const activeMix = jamTrack.mixdowns.find(mix => mix.id === selectedOption.value);
getMixdownAudioUrl(activeMix.id).then(audioUrl => { getMixdownAudioUrl(activeMix.id).then(audioUrl => {
console.log('_DEBUG_ audioUrl', audioUrl);
setAudioUrl(audioUrl); setAudioUrl(audioUrl);
markMixdownActive({ id: jamTrack.id, mixdown_id: activeMix.id }); markMixdownActive({ id: jamTrack.id, mixdown_id: activeMix.id });
if (audioRef.current) { if (audioRef.current) {
@ -85,12 +86,10 @@ const JKJamTrackPlayer = () => {
}); });
} }
}else if(selectedOption.data.type === 'stem') { } else if (selectedOption.data.type === 'stem') {
const activeTrack = jamTrack.tracks.find(track => track.id === selectedOption.value); const activeTrack = jamTrack.tracks.find(track => track.id === selectedOption.value);
console.log('_DEBUG_ activeTrack', activeTrack);
getStemAudioUrl(activeTrack.id).then(audioUrl => { getStemAudioUrl(activeTrack.id).then(audioUrl => {
console.log('_DEBUG_ audioUrl', audioUrl);
setAudioUrl(audioUrl); setAudioUrl(audioUrl);
markMixdownActive({ id: jamTrack.id, mixdown_id: null, stem_id: activeTrack.id }); markMixdownActive({ id: jamTrack.id, mixdown_id: null, stem_id: activeTrack.id });
if (audioRef.current) { if (audioRef.current) {
@ -109,26 +108,91 @@ const JKJamTrackPlayer = () => {
sample_rate: SAMPLE_RATE, sample_rate: SAMPLE_RATE,
origin: 'player' origin: 'player'
}; };
console.log('enqueueMyMixdown', options);
enqueueMixdownForSigning(options); enqueueMixdownForSigning(options);
} }
} }
useEffect(() => { useEffect(() => {
if (enqueuedMixdown && enqueuedMixdown.origin === 'player') { if (enqueuedMixdown && enqueuedMixdown.origin === 'player') {
console.log('*_DEBUG_ enqueuedMixdown from player', enqueuedMixdown);
showEstimatedTime(); showEstimatedTime();
manageWatchedMixdowns(); manageWatchedMixdowns();
} }
}, [enqueuedMixdown]); }, [enqueuedMixdown]);
const handleDownloadClick = async () => {
if (!selectedOption) {
return;
}
if(!jamTrack.can_download) {
console.log('Cannot download JamTrack');
return;
}
if (selectedOption.data.type === 'master') {
await downloadMaster();
} else if (selectedOption.data.type === 'custom-mix') {
const activeMix = jamTrack.mixdowns.find(mix => mix.id === selectedOption.value);
await downloadMixdown(activeMix);
} else if (selectedOption.data.type === 'stem') {
await downloadTrack();
}
}
const downloadMaster = async () => {
const fp = await fpPromise;
const result = await fp.get();
const src = `${process.env.REACT_APP_API_BASE_URL}/jamtracks/${jamTrack.id
}/stems/master/download.mp3?file_type=mp3&download=1&mark=${result.visitorId}`;
openDownload(src);
};
const downloadMixdown = async (mixdown) => {
const mixdownPackage = mixdown.packages.find(p => p.file_type === 'mp3');
if (mixdownPackage?.signing_state == 'SIGNED') {
const fp = await fpPromise;
const result = await fp.get();
const src = `${process.env.REACT_APP_API_BASE_URL}/mixdowns/${mixdown.id
}/download.mp3?file_type=mp3&sample_rate=48&download=1&mark=${result.visitorId}`;
openDownload(src);
} else {
console.log('Mixdown not signed');
}
};
const downloadTrack = async (track) => {
const activeTrack = jamTrack.tracks.find(track => track.id === selectedOption.value);
if (activeTrack) {
const fp = await fpPromise;
const result = await fp.get();
const src = `${process.env.REACT_APP_API_BASE_URL}/jamtracks/${jamTrack.id
}/stems/${activeTrack.id}/download.mp3?file_type=mp3&download=1&mark=${result.visitorId}`;
openDownload(src);
}
}
const openDownload = async src => {
const iframe = document.createElement('iframe');
iframe.src = src;
iframe.style.display = 'none';
document.body.appendChild(iframe);
};
return ( return (
<> <>
<Select options={options} placeholder="Select Mix" onChange={handleOnChange} value={selectedOption} /> <Select
options={options}
placeholder="Select Mix"
onChange={handleOnChange}
value={selectedOption}
styles={{
// Fixes the overlapping problem of the component
menu: (base) => ({ ...base, zIndex: 9999 })
}}
/>
<Row className="mt-2"> <Row className="mt-2">
<Col> <Col>
{audioUrl && ( {audioUrl && (
<JKAudioPlayer audioUrl={audioUrl} /> <JKAudioPlayer audioUrl={audioUrl} onDownloadClick={handleDownloadClick} />
)} )}
</Col> </Col>
</Row> </Row>

View File

@ -51,6 +51,14 @@ const JKJamTrackShow = () => {
<div>Loading...</div> <div>Loading...</div>
) : jamTrack ? ( ) : jamTrack ? (
<> <>
<Row>
<Col>
<h4>
JamTrack: {jamTrack.name} by {jamTrack.original_artist}
</h4>
</Col>
</Row>
<Row className='mb-3'> <Row className='mb-3'>
<Col> <Col>
<Link to="/my-jamtracks">{`< Back to My JamTracks`}</Link> <Link to="/my-jamtracks">{`< Back to My JamTracks`}</Link>

View File

@ -5,6 +5,8 @@ import { Howl } from 'howler';
import { useJamTrackPreview } from '../../context/JamTrackPreviewContext'; import { useJamTrackPreview } from '../../context/JamTrackPreviewContext';
import { Spinner } from 'reactstrap'; import { Spinner } from 'reactstrap';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import playIcon from '../../assets/img/icons/play-icon.svg';
import pauseIcon from '../../assets/img/icons/pause-icon.svg';
const JKJamTrackTrack = ({ track }) => { const JKJamTrackTrack = ({ track }) => {
const [isPlaying, setIsPlaying] = useState(false); const [isPlaying, setIsPlaying] = useState(false);
@ -107,7 +109,14 @@ const JKJamTrackTrack = ({ track }) => {
return ( return (
<div className="mb-1 d-flex align-items-center jamtrack-track"> <div className="mb-1 d-flex align-items-center jamtrack-track">
<span className="mr-1"> <span className="mr-1">
<FontAwesomeIcon icon={isPlaying ? 'pause-circle' : 'play-circle'} size="2x" onClick={togglePlay} /> {/* <FontAwesomeIcon icon={isPlaying ? 'pause-circle' : 'play-circle'} size="2x" onClick={togglePlay} /> */}
<button onClick={togglePlay} style={{ border: 'none', background: 'none' }}>
{isPlaying ? (
<img src={pauseIcon} alt="Pause" width="30" />
) : (
<img src={playIcon} alt="Play" width="30" />
)}
</button>
</span> </span>
{trackInfo && ( {trackInfo && (
<> <>

View File

@ -8,6 +8,7 @@ import { SAMPLE_RATE } from '../../helpers/jamTracks';
import { useJamTrack } from '../../hooks/useJamTrack'; import { useJamTrack } from '../../hooks/useJamTrack';
import JKSigningRetryConfirmModal from './JKSigningRetryConfirmModal'; import JKSigningRetryConfirmModal from './JKSigningRetryConfirmModal';
import JKSigningEstimateTimeModal from './JKSigningEstimateTimeModal'; import JKSigningEstimateTimeModal from './JKSigningEstimateTimeModal';
import deleteIcon from '../../assets/img/icons/delete-icon.svg';
const JKMyJamTrackMixes = () => { const JKMyJamTrackMixes = () => {
const [selectedMixdown, setSelectedMixdown] = useState(null); const [selectedMixdown, setSelectedMixdown] = useState(null);
@ -32,39 +33,6 @@ const JKMyJamTrackMixes = () => {
trackName trackName
} = useJamTrack(); } = useJamTrack();
const downloadJamTrack = async () => {
console.log('Downloading JamTrack');
if (!jamTrack.can_download) {
console.log('Cannot download JamTrack');
return;
}
const fp = await fpPromise;
const result = await fp.get();
const src = `${process.env.REACT_APP_API_BASE_URL}/jamtracks/${jamTrack.id
}/stems/master/download.mp3?file_type=mp3&download=1&mark=${result.visitorId}`;
openDownload(src);
};
const downloadMix = async (mixdown) => {
const mixdownPackage = mixdown.packages.find(p => p.file_type === 'mp3');
if (mixdownPackage?.signing_state == 'SIGNED') {
const fp = await fpPromise;
const result = await fp.get();
const src = `${process.env.REACT_APP_API_BASE_URL}/mixdowns/${mixdown.id
}/download.mp3?file_type=mp3&sample_rate=48&download=1&mark=${result.visitorId}`;
openDownload(src);
} else {
console.log('Mixdown not signed');
}
};
const openDownload = async src => {
const iframe = document.createElement('iframe');
iframe.src = src;
iframe.style.display = 'none';
document.body.appendChild(iframe);
};
const deleteMix = mixdown => { const deleteMix = mixdown => {
const { id } = mixdown; const { id } = mixdown;
if (window.confirm('Delete this custom mix?')) { if (window.confirm('Delete this custom mix?')) {
@ -94,7 +62,7 @@ const JKMyJamTrackMixes = () => {
useEffect(() => { useEffect(() => {
if (enqueuedMixdown && enqueuedMixdown.origin === 'mixes') { if (enqueuedMixdown && enqueuedMixdown.origin === 'mixes') {
console.log('*_DEBUG_ enqueuedMixdown from mixes', enqueuedMixdown); //console.log('*_DEBUG_ enqueuedMixdown from mixes', enqueuedMixdown);
showEstimatedTime(); showEstimatedTime();
manageWatchedMixdowns(); manageWatchedMixdowns();
} }
@ -118,22 +86,23 @@ const JKMyJamTrackMixes = () => {
You can save a <strong>maximum of 5 mixes</strong> on JamKazam. If you need to make more mixes, download a mix You can save a <strong>maximum of 5 mixes</strong> on JamKazam. If you need to make more mixes, download a mix
to save it, then delete it to make more room to save it, then delete it to make more room
</p> </p>
{ mixdowns.length > 0 && (
<Table striped bordered className="fs--1"> <Table striped bordered className="fs--1">
<thead className="bg-200 text-900"> <thead className="bg-200 text-900">
<tr> <tr>
<th>Mix</th> <th>Mix</th>
<th className="text-center">Actions</th> <th className="text-center">Delete</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> {/* <tr>
<td>Full JamTrack</td> <td>Full JamTrack</td>
<td className="text-center"> <td className="text-center">
<a onClick={downloadJamTrack}> <a onClick={downloadJamTrack}>
<FontAwesomeIcon icon="download" size="lg" className="mr-3" /> <FontAwesomeIcon icon="download" size="lg" className="mr-3" />
</a> </a>
</td> </td>
</tr> </tr> */}
{mixdowns.map(mixdown => ( {mixdowns.map(mixdown => (
<tr key={mixdown.id}> <tr key={mixdown.id}>
<td> <td>
@ -142,15 +111,16 @@ const JKMyJamTrackMixes = () => {
<td className="text-center"> <td className="text-center">
{isMixdownPackageReady(mixdown) ? ( {isMixdownPackageReady(mixdown) ? (
<> <>
<a onClick={() => downloadMix(mixdown)} style={{ cursor: 'pointer' }}> {/* <a onClick={() => downloadMix(mixdown)} style={{ cursor: 'pointer' }}>
<FontAwesomeIcon icon="download" size="lg" className="mr-3" /> <FontAwesomeIcon icon="download" size="lg" className="mr-3" />
</a> </a> */}
<a <a
onClick={() => deleteMix(mixdown)} onClick={() => deleteMix(mixdown)}
disabled={deleteMixdownStatus === 'loading'} disabled={deleteMixdownStatus === 'loading'}
style={{ cursor: 'pointer' }} style={{ cursor: 'pointer' }}
> >
<FontAwesomeIcon icon="trash" size="lg" /> {/* <FontAwesomeIcon icon="trash" size="lg" /> */}
<img src={deleteIcon} alt="Delete" height={20} />
</a> </a>
</> </>
) : ( ) : (
@ -161,15 +131,18 @@ const JKMyJamTrackMixes = () => {
</Spinner> </Spinner>
) : ( ) : (
<> <>
{ mixdownPackage(mixdown) && ['ERROR', 'SIGNING_TIMEOUT', 'QUEUED_TIMEOUT', 'QUIET'].includes(mixdownPackage(mixdown).signing_state) && (
<a onClick={() => confirmRetry(mixdown)} style={{ cursor: 'pointer' }}> <a onClick={() => confirmRetry(mixdown)} style={{ cursor: 'pointer' }}>
<FontAwesomeIcon icon="exclamation-circle" size="lg" className="mr-3" /> <FontAwesomeIcon icon="exclamation-circle" size="lg" className="mr-3" />
</a> </a>
)}
<a <a
onClick={() => deleteMix(mixdown)} onClick={() => deleteMix(mixdown)}
disabled={deleteMixdownStatus === 'loading'} disabled={deleteMixdownStatus === 'loading'}
style={{ cursor: 'pointer' }} style={{ cursor: 'pointer' }}
> >
<FontAwesomeIcon icon="trash" size="lg" /> {/* <FontAwesomeIcon icon="trash" size="lg" /> */}
<img src={deleteIcon} alt="Delete" height={20} />
</a> </a>
</> </>
)} )}
@ -193,6 +166,7 @@ const JKMyJamTrackMixes = () => {
))} */} ))} */}
</tbody> </tbody>
</Table> </Table>
)}
<JKSigningRetryConfirmModal <JKSigningRetryConfirmModal
showRetryConfirm={showRetryConfirm} showRetryConfirm={showRetryConfirm}
setShowRetryConfirm={setShowRetryConfirm} setShowRetryConfirm={setShowRetryConfirm}

View File

@ -11,7 +11,7 @@ export const fetchUserLatencies = createAsyncThunk(
'latency/fetchUserLatencies', 'latency/fetchUserLatencies',
async (options, thunkAPI) => { async (options, thunkAPI) => {
const { currentUserId, otherUserIds } = options const { currentUserId, otherUserIds } = options
console.log('X_DEBUG_ fetchUserLatencies', currentUserId, otherUserIds) //console.log('_DEBUG_ fetchUserLatencies', currentUserId, otherUserIds)
const response = await getLatencyToUsers(currentUserId, otherUserIds) const response = await getLatencyToUsers(currentUserId, otherUserIds)
return response.json() return response.json()
} }

View File

@ -627,7 +627,7 @@
} }
server.registerMessageCallback = function (messageType, callback) { server.registerMessageCallback = function (messageType, callback) {
console.log("_DEBUG_ jamserver server.registerMessageCallback", messageType, callback) console.log("server.registerMessageCallback", messageType, callback)
if (server.dispatchTable[messageType] === undefined) { if (server.dispatchTable[messageType] === undefined) {
server.dispatchTable[messageType] = []; server.dispatchTable[messageType] = [];
} }

View File

@ -607,7 +607,7 @@
} }
server.registerMessageCallback = function (messageType, callback) { server.registerMessageCallback = function (messageType, callback) {
console.log("_DEBUG_ jamserver_copy server.registerMessageCallback", messageType, callback) console.log("server.registerMessageCallback", messageType, callback)
if (server.dispatchTable[messageType] === undefined) { if (server.dispatchTable[messageType] === undefined) {
server.dispatchTable[messageType] = []; server.dispatchTable[messageType] = [];
} }