Browse Source

update player functionality

master
jeffvli 3 years ago
parent
commit
0ec986865f
  1. 1
      package.json
  2. 3
      src/App.tsx
  3. 3
      src/components/layout/styled.tsx
  4. 62
      src/components/player/Player.tsx
  5. 319
      src/components/player/PlayerBar.tsx
  6. 39
      src/redux/playQueueSlice.ts
  7. 24
      yarn.lock

1
package.json

@ -252,6 +252,7 @@
"electron-redux": "^1.5.4", "electron-redux": "^1.5.4",
"electron-settings": "^4.0.2", "electron-settings": "^4.0.2",
"electron-updater": "^4.3.4", "electron-updater": "^4.3.4",
"format-duration": "^1.4.0",
"history": "^5.0.0", "history": "^5.0.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"md5": "^2.3.0", "md5": "^2.3.0",

3
src/App.tsx

@ -6,7 +6,6 @@ import PlaylistList from './components/playlist/PlaylistList';
import PlaylistView from './components/playlist/PlaylistView'; import PlaylistView from './components/playlist/PlaylistView';
import Settings from './components/settings/Settings'; import Settings from './components/settings/Settings';
import NowPlayingView from './components/player/NowPlayingView'; import NowPlayingView from './components/player/NowPlayingView';
import Player from './components/player/Player';
import Login from './components/settings/Login'; import Login from './components/settings/Login';
import StarredView from './components/starred/StarredView'; import StarredView from './components/starred/StarredView';
import Dashboard from './components/dashboard/Dashboard'; import Dashboard from './components/dashboard/Dashboard';
@ -19,7 +18,6 @@ const App = () => {
} }
return ( return (
<Player>
<Router> <Router>
<Layout footer={<PlayerBar />}> <Layout footer={<PlayerBar />}>
<Switch> <Switch>
@ -35,7 +33,6 @@ const App = () => {
</Switch> </Switch>
</Layout> </Layout>
</Router> </Router>
</Player>
); );
}; };

3
src/components/layout/styled.tsx

@ -5,7 +5,6 @@ import { Container, Content, Footer, Header, Sidebar } from 'rsuite';
// Layout.tsx // Layout.tsx
export const RootContainer = styled(Container)` export const RootContainer = styled(Container)`
height: 100vh; height: 100vh;
padding-bottom: 10px;
`; `;
interface ContainerProps { interface ContainerProps {
@ -29,7 +28,7 @@ export const MainContainer = styled(StyledContainer)`
`; `;
export const RootFooter = styled(Footer)` export const RootFooter = styled(Footer)`
height: 88px; height: 98px;
`; `;
// Titlebar.tsx // Titlebar.tsx

62
src/components/player/Player.tsx

@ -1,4 +1,11 @@
import React, { useState, createContext, useRef, useEffect } from 'react'; import React, {
useState,
createContext,
useRef,
useEffect,
useImperativeHandle,
forwardRef,
} from 'react';
import ReactAudioPlayer from 'react-audio-player'; import ReactAudioPlayer from 'react-audio-player';
import { useAppDispatch, useAppSelector } from '../../redux/hooks'; import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import { import {
@ -6,19 +13,27 @@ import {
incrementPlayerIndex, incrementPlayerIndex,
setCurrentPlayer, setCurrentPlayer,
setPlayerVolume, setPlayerVolume,
setCurrentSeek,
} from '../../redux/playQueueSlice'; } from '../../redux/playQueueSlice';
export const PlayerContext = createContext<any>({}); export const PlayerContext = createContext<any>({});
const Player = ({ children }: any) => { const Player = ({ children }: any, ref: any) => {
const [incremented, setIncremented] = useState(false); const [incremented, setIncremented] = useState(false);
const player1Ref = useRef<any>(); const player1Ref = useRef<any>();
const player2Ref = useRef<any>(); const player2Ref = useRef<any>();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const playQueue = useAppSelector((state) => state.playQueue); const playQueue = useAppSelector((state) => state.playQueue);
useImperativeHandle(ref, () => ({
get player1() {
return player1Ref.current;
},
get player2() {
return player2Ref.current;
},
}));
useEffect(() => { useEffect(() => {
if (playQueue.status === 'PLAYING') { if (playQueue.status === 'PLAYING') {
if (playQueue.currentPlayer === 1) { if (playQueue.currentPlayer === 1) {
@ -42,11 +57,11 @@ const Player = ({ children }: any) => {
const handleListen = () => { const handleListen = () => {
const fadeDuration = 10; const fadeDuration = 10;
const currentTime = player1Ref.current?.audioEl.current?.currentTime || 0; const currentSeek = player1Ref.current?.audioEl.current?.currentTime || 0;
const duration = player1Ref.current?.audioEl.current?.duration; const duration = player1Ref.current?.audioEl.current?.duration;
const fadeAtTime = duration - fadeDuration; const fadeAtTime = duration - fadeDuration;
if (currentTime >= fadeAtTime) { if (currentSeek >= fadeAtTime) {
if (player2Ref.current.audioEl.current) { if (player2Ref.current.audioEl.current) {
// Once fading starts, start playing player 2 and set current to 2 // Once fading starts, start playing player 2 and set current to 2
const player1Volume = const player1Volume =
@ -72,17 +87,19 @@ const Player = ({ children }: any) => {
dispatch(setCurrentPlayer(2)); dispatch(setCurrentPlayer(2));
} }
console.log('fading player1...'); console.log('fading player1...');
} else {
dispatch(setCurrentSeek(currentSeek));
} }
console.log(`player1: ${currentTime} / ${fadeAtTime}`); console.log(`player1: ${currentSeek} / ${fadeAtTime}`);
}; };
const handleListen2 = () => { const handleListen2 = () => {
const fadeDuration = 10; const fadeDuration = 10;
const currentTime = player2Ref.current?.audioEl.current?.currentTime || 0; const currentSeek = player2Ref.current?.audioEl.current?.currentTime || 0;
const duration = player2Ref.current?.audioEl.current?.duration; const duration = player2Ref.current?.audioEl.current?.duration;
const fadeAtTime = duration - fadeDuration; const fadeAtTime = duration - fadeDuration;
if (currentTime >= fadeAtTime) { if (currentSeek >= fadeAtTime) {
if (player1Ref.current.audioEl.current) { if (player1Ref.current.audioEl.current) {
// Once fading starts, start playing player 1 and set current to 1 // Once fading starts, start playing player 1 and set current to 1
const player1Volume = const player1Volume =
@ -108,8 +125,11 @@ const Player = ({ children }: any) => {
dispatch(setCurrentPlayer(1)); dispatch(setCurrentPlayer(1));
} }
console.log('fading player2...'); console.log('fading player2...');
} else {
dispatch(setCurrentSeek(currentSeek));
} }
console.log(`player2: ${currentTime} / ${fadeAtTime}`);
console.log(`player2: ${currentSeek} / ${fadeAtTime}`);
}; };
const handleOnEnded1 = () => { const handleOnEnded1 = () => {
@ -126,22 +146,6 @@ const Player = ({ children }: any) => {
setIncremented(false); setIncremented(false);
}; };
/* const handleOnLoadStart = () => {
dispatch(setIsLoading());
};
const handleOnLoadedData = () => {
dispatch(setIsLoaded());
};
const handleOnClickNext = () => {
dispatch(incrementCurrentIndex());
};
const handleOnClickPrevious = () => {
dispatch(decrementCurrentIndex());
}; */
return ( return (
<PlayerContext.Provider <PlayerContext.Provider
value={{ value={{
@ -150,7 +154,6 @@ const Player = ({ children }: any) => {
}} }}
> >
<ReactAudioPlayer <ReactAudioPlayer
style={{ position: 'absolute' }}
ref={player1Ref} ref={player1Ref}
src={playQueue.entry[playQueue.player1.index]?.streamUrl} src={playQueue.entry[playQueue.player1.index]?.streamUrl}
listenInterval={500} listenInterval={500}
@ -158,11 +161,9 @@ const Player = ({ children }: any) => {
onListen={handleListen} onListen={handleListen}
onEnded={handleOnEnded1} onEnded={handleOnEnded1}
volume={playQueue.player1.volume} volume={playQueue.player1.volume}
controls
autoPlay={playQueue.player1.index === playQueue.currentIndex} autoPlay={playQueue.player1.index === playQueue.currentIndex}
/> />
<ReactAudioPlayer <ReactAudioPlayer
style={{ position: 'absolute' }}
ref={player2Ref} ref={player2Ref}
src={playQueue.entry[playQueue.player2.index]?.streamUrl} src={playQueue.entry[playQueue.player2.index]?.streamUrl}
listenInterval={500} listenInterval={500}
@ -170,7 +171,6 @@ const Player = ({ children }: any) => {
onListen={handleListen2} onListen={handleListen2}
onEnded={handleOnEnded2} onEnded={handleOnEnded2}
volume={playQueue.player2.volume} volume={playQueue.player2.volume}
controls
autoPlay={playQueue.player2.index === playQueue.currentIndex} autoPlay={playQueue.player2.index === playQueue.currentIndex}
/> />
{children} {children}
@ -178,4 +178,4 @@ const Player = ({ children }: any) => {
); );
}; };
export default Player; export default forwardRef(Player);

319
src/components/player/PlayerBar.tsx

@ -1,132 +1,229 @@
import React, { useContext, useEffect, useRef } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import ReactAudioPlayer from 'react-audio-player'; import { FlexboxGrid, Icon, Slider, Button } from 'rsuite';
import { Button } from 'rsuite'; import format from 'format-duration';
import { useAppDispatch, useAppSelector } from '../../redux/hooks'; import styled from 'styled-components';
import { import {
incrementCurrentIndex, incrementCurrentIndex,
incrementPlayerIndex, decrementCurrentIndex,
setVolume,
setPlayerVolume,
setStatus,
} from '../../redux/playQueueSlice'; } from '../../redux/playQueueSlice';
import { PlayerContext } from './Player'; import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import Player from './Player';
import 'react-rangeslider/lib/index.css';
const PlayerBar = () => { const PlayerContainer = styled.div`
const player1Ref = useRef<any>(); background: #000000;
const player2Ref = useRef<any>(); height: 100%;
const { border-top: 1px solid #48545c;
player1Volume, `;
player2Volume,
setPlayer1Volume,
setPlayer2Volume,
incremented,
setIncremented,
globalVolume,
currentPlayer,
setCurrentPlayer,
} = useContext(PlayerContext);
const dispatch = useAppDispatch(); const PlayerColumn = styled.div<{
const playQueue = useAppSelector((state) => state.playQueue); left?: boolean;
center?: boolean;
right?: boolean;
height: string;
}>`
height: ${(props) => props.height};
display: flex;
align-items: center;
justify-content: ${(props) =>
props.left
? 'flex-start'
: props.center
? 'center'
: props.right
? 'flex-end'
: 'center'};
`;
const handleListen = () => { const PlayerControlIcon = styled(Icon)`
const fadeDuration = 10; color: #b3b3b3;
const currentTime = player1Ref.current?.audioEl.current?.currentTime || 0; padding: 0 15px 0 15px;
const duration = player1Ref.current?.audioEl.current?.duration; &:hover {
const fadeAtTime = duration - fadeDuration; color: #fff;
if (currentTime >= fadeAtTime) {
if (player2Ref.current.audioEl.current) {
// Once fading starts, start playing player 2 and set current to 2
setPlayer1Volume(
player1Volume - globalVolume / (fadeDuration * 2) <= 0
? 0
: player1Volume - globalVolume / (fadeDuration * 2)
);
setPlayer2Volume(
player2Volume + globalVolume / (fadeDuration * 1.5) >= globalVolume
? globalVolume
: player2Volume + globalVolume / (fadeDuration * 1.5)
);
player2Ref.current.audioEl.current.play();
if (!incremented) {
dispatch(incrementCurrentIndex('none'));
setIncremented(true);
} }
setCurrentPlayer(2); `;
const PlayerBar = () => {
const playQueue = useAppSelector((state) => state.playQueue);
const dispatch = useAppDispatch();
const [seek, setSeek] = useState(0);
const [isDragging, setIsDragging] = useState(false);
const [manualSeek, setManualSeek] = useState(0);
const [isLoading, setIsLoading] = useState(false);
const playersRef = useRef<any>();
useEffect(() => {
setSeek(playQueue.currentSeek);
}, [playQueue.currentSeek]);
useEffect(() => {
if (isDragging) {
if (playQueue.currentPlayer === 1) {
playersRef.current.player1.audioEl.current.currentTime = manualSeek;
} else {
playersRef.current.player2.audioEl.current.currentTime = manualSeek;
} }
console.log('fading player1...');
// Wait for the seek to catch up, otherwise the bar will bounce back and forth
setTimeout(() => {
setIsDragging(false);
}, 1500);
} }
console.log(`player1: ${currentTime} / ${fadeAtTime}`); }, [isDragging, manualSeek, playQueue.currentPlayer]);
/* const handleOnLoadStart = () => {
dispatch(setIsLoading());
}; };
const handleListen2 = () => { const handleOnLoadedData = () => {
const fadeDuration = 10; dispatch(setIsLoaded());
const currentTime = player2Ref.current?.audioEl.current?.currentTime || 0; }; */
const duration = player2Ref.current?.audioEl.current?.duration;
const fadeAtTime = duration - fadeDuration; const handleClickNext = () => {
dispatch(incrementCurrentIndex('usingHotkey'));
if (currentTime >= fadeAtTime) { };
if (player1Ref.current.audioEl.current) {
// Once fading starts, start playing player 1 and set current to 1 const handleClickPrevious = () => {
setPlayer1Volume( dispatch(decrementCurrentIndex('usingHotkey'));
player1Volume + globalVolume / (fadeDuration * 1.5) >= globalVolume };
? globalVolume
: player1Volume + globalVolume / (fadeDuration * 1.5) const handleClickPlayPause = () => {
); dispatch(setStatus(playQueue.status === 'PLAYING' ? 'PAUSED' : 'PLAYING'));
setPlayer2Volume( };
player2Volume - globalVolume / (fadeDuration * 2) <= 0
? 0 const handleVolumeSlider = (e: number) => {
: player2Volume - globalVolume / (fadeDuration * 2) const vol = Number((e / 100).toFixed(2));
); dispatch(setVolume(vol));
player1Ref.current.audioEl.current.play(); dispatch(setPlayerVolume({ player: playQueue.currentPlayer, volume: vol }));
if (!incremented) {
dispatch(incrementCurrentIndex('none'));
setIncremented(true);
}
setCurrentPlayer(1);
}
console.log('fading player2...');
}
console.log(`player2: ${currentTime} / ${fadeAtTime}`);
}; };
const handleOnEnded1 = () => { const handleSeekSlider = (e: number) => {
dispatch(incrementPlayerIndex(1)); setIsDragging(true);
setPlayer1Volume(0); setManualSeek(e);
setPlayer2Volume(globalVolume); console.log(e);
setIncremented(false);
}; };
const handleOnEnded2 = () => { const handleOnWaiting = () => {
dispatch(incrementPlayerIndex(2)); /* console.log(
setPlayer1Volume(globalVolume); (playersRef.current?.player1.audioEl.current.onwaiting = () => {
setPlayer2Volume(0); console.log('Waiting');
setIncremented(false); })
); */
}; };
return ( return (
<> <PlayerContainer>
<ReactAudioPlayer <Player ref={playersRef} isDragging={isDragging} />
ref={player1Ref} <Button onClick={handleOnWaiting} />
src={playQueue.entry[playQueue.player1Index]?.streamUrl}
listenInterval={500} <FlexboxGrid align="middle" style={{ height: '100%' }}>
preload="auto" <FlexboxGrid.Item
onListen={handleListen} colspan={6}
onEnded={handleOnEnded1} style={{ textAlign: 'left', paddingLeft: '25px' }}
controls >
volume={player1Volume} <PlayerColumn left height="50px">
autoPlay={playQueue.player1Index === playQueue.currentIndex} <div>Is seeking: {isDragging ? 'true' : 'false'}</div>
</PlayerColumn>
</FlexboxGrid.Item>
<FlexboxGrid.Item
colspan={12}
style={{ textAlign: 'center', verticalAlign: 'middle' }}
>
<PlayerColumn center height="45px">
<PlayerControlIcon icon="random" size="lg" />
<PlayerControlIcon
icon="step-backward"
size="lg"
onClick={handleClickPrevious}
/>
<PlayerControlIcon
icon={
playQueue.status === 'PLAYING' ? 'pause-circle' : 'play-circle'
}
size="3x"
onClick={handleClickPlayPause}
/>
<PlayerControlIcon
icon="step-forward"
size="lg"
onClick={handleClickNext}
/>
<PlayerControlIcon
icon="repeat"
size="lg"
onClick={() => console.log('h')}
/>
</PlayerColumn>
<PlayerColumn center height="35px">
<FlexboxGrid
justify="center"
style={{
width: '100%',
display: 'flex',
alignItems: 'center',
height: '35px',
}}
>
<FlexboxGrid.Item
colspan={4}
style={{ textAlign: 'right', paddingRight: '10px' }}
>
{format((isDragging ? manualSeek : seek) * 1000)}
</FlexboxGrid.Item>
<FlexboxGrid.Item colspan={16}>
<Slider
progress
defaultValue={0}
value={isDragging ? manualSeek : seek}
tooltip={false}
max={
playQueue.entry[playQueue.currentIndex]?.duration -
10 * 1.3 || 0
}
onChange={handleSeekSlider}
style={{ width: '100%' }}
/>
</FlexboxGrid.Item>
<FlexboxGrid.Item
colspan={4}
style={{ textAlign: 'left', paddingLeft: '10px' }}
>
{format(
playQueue.entry[playQueue.currentIndex]?.duration * 1000 || 0
)}
</FlexboxGrid.Item>
</FlexboxGrid>
</PlayerColumn>
</FlexboxGrid.Item>
<FlexboxGrid.Item
colspan={6}
style={{ textAlign: 'right', paddingRight: '25px' }}
>
<PlayerColumn right height="45px">
<Icon
icon={
playQueue.volume > 0.7
? 'volume-up'
: playQueue.volume < 0.3
? 'volume-off'
: 'volume-down'
}
size="lg"
style={{ marginRight: '15px' }}
/> />
<ReactAudioPlayer <Slider
ref={player2Ref} progress
src={playQueue.entry[playQueue.player2Index]?.streamUrl} value={Math.floor(playQueue.volume * 100)}
listenInterval={500} style={{ width: '80px' }}
preload="auto" onChange={handleVolumeSlider}
onListen={handleListen2}
onEnded={handleOnEnded2}
controls
volume={player2Volume}
autoPlay={playQueue.player2Index === playQueue.currentIndex}
/> />
<Button onClick={() => console.log(playQueue.entry)}>Length</Button> </PlayerColumn>
</FlexboxGrid.Item>
</FlexboxGrid>
{/* <Button onClick={() => console.log(playQueue.entry)}>Length</Button>
<div> <div>
{`Current index: ${playQueue.currentIndex} | `} {`Current index: ${playQueue.currentIndex} | `}
{`Player1 index: ${playQueue.player1Index} - ${ {`Player1 index: ${playQueue.player1Index} - ${
@ -136,8 +233,8 @@ const PlayerBar = () => {
playQueue.entry[playQueue.player2Index]?.title playQueue.entry[playQueue.player2Index]?.title
} | `} } | `}
{`CurrentPlayer: ${playQueue.currentPlayer}`} {`CurrentPlayer: ${playQueue.currentPlayer}`}
</div> </div> */}
</> </PlayerContainer>
); );
}; };

39
src/redux/playQueueSlice.ts

@ -34,6 +34,7 @@ export interface PlayQueue {
currentIndex: number; currentIndex: number;
currentSongId: string; currentSongId: string;
currentPlayer: number; currentPlayer: number;
currentSeek: number;
player1: { player1: {
index: number; index: number;
volume: number; volume: number;
@ -53,6 +54,7 @@ const initialState: PlayQueue = {
currentIndex: 0, currentIndex: 0,
currentSongId: '', currentSongId: '',
currentPlayer: 1, currentPlayer: 1,
currentSeek: 0,
player1: { player1: {
index: 0, index: 0,
volume: 0.5, volume: 0.5,
@ -72,7 +74,17 @@ const playQueueSlice = createSlice({
initialState, initialState,
reducers: { reducers: {
setStatus: (state, action: PayloadAction<string>) => { setStatus: (state, action: PayloadAction<string>) => {
if (state.entry.length >= 1) {
state.status = action.payload; state.status = action.payload;
}
},
setVolume: (state, action: PayloadAction<number>) => {
state.volume = action.payload;
},
setCurrentSeek: (state, action: PayloadAction<number>) => {
state.currentSeek = action.payload;
}, },
setCurrentPlayer: (state, action: PayloadAction<number>) => { setCurrentPlayer: (state, action: PayloadAction<number>) => {
@ -85,6 +97,7 @@ const playQueueSlice = createSlice({
incrementCurrentIndex: (state, action: PayloadAction<string>) => { incrementCurrentIndex: (state, action: PayloadAction<string>) => {
if (state.entry.length >= 1) { if (state.entry.length >= 1) {
state.currentSeek = 0;
if (state.currentIndex < state.entry.length - 1) { if (state.currentIndex < state.entry.length - 1) {
state.currentIndex += 1; state.currentIndex += 1;
if (action.payload === 'usingHotkey') { if (action.payload === 'usingHotkey') {
@ -123,6 +136,7 @@ const playQueueSlice = createSlice({
(track) => track.id === action.payload.id (track) => track.id === action.payload.id
); );
state.currentSeek = 0;
state.player1.index = findIndex; state.player1.index = findIndex;
state.player1.volume = state.volume; state.player1.volume = state.volume;
state.player2.index = findIndex + 1; state.player2.index = findIndex + 1;
@ -145,6 +159,7 @@ const playQueueSlice = createSlice({
decrementCurrentIndex: (state, action: PayloadAction<string>) => { decrementCurrentIndex: (state, action: PayloadAction<string>) => {
if (state.entry.length >= 1) { if (state.entry.length >= 1) {
state.currentSeek = 0;
if (state.currentIndex > 0) { if (state.currentIndex > 0) {
state.currentIndex -= 1; state.currentIndex -= 1;
if (action.payload === 'usingHotkey') { if (action.payload === 'usingHotkey') {
@ -168,10 +183,19 @@ const playQueueSlice = createSlice({
}, },
setPlayQueue: (state, action: PayloadAction<Entry[]>) => { setPlayQueue: (state, action: PayloadAction<Entry[]>) => {
// Reset player defaults
state.entry = [];
state.status = 'PAUSED';
state.currentIndex = 0;
state.currentSongId = '';
state.currentPlayer = 1;
state.currentSeek = 0;
state.player1.index = 0;
state.player2.index = 1;
if (state.status !== 'PLAYING') { if (state.status !== 'PLAYING') {
state.status = 'PLAYING'; state.status = 'PLAYING';
} }
state.currentIndex = 0;
state.currentSongId = action.payload[0].id; state.currentSongId = action.payload[0].id;
action.payload.map((entry: any) => state.entry.push(entry)); action.payload.map((entry: any) => state.entry.push(entry));
}, },
@ -180,7 +204,16 @@ const playQueueSlice = createSlice({
action.payload.map((entry: any) => state.entry.push(entry)); action.payload.map((entry: any) => state.entry.push(entry));
}, },
clearPlayQueue: () => initialState, clearPlayQueue: (state) => {
state.entry = [];
state.status = 'PAUSED';
state.currentIndex = 0;
state.currentSongId = '';
state.currentPlayer = 1;
state.currentSeek = 0;
state.player1.index = 0;
state.player2.index = 1;
},
setIsLoading: (state) => { setIsLoading: (state) => {
state.isLoading = true; state.isLoading = true;
@ -269,5 +302,7 @@ export const {
setCurrentPlayer, setCurrentPlayer,
setStatus, setStatus,
setPlayerVolume, setPlayerVolume,
setVolume,
setCurrentSeek,
} = playQueueSlice.actions; } = playQueueSlice.actions;
export default playQueueSlice.reducer; export default playQueueSlice.reducer;

24
yarn.lock

@ -1064,9 +1064,9 @@
regenerator-runtime "^0.13.4" regenerator-runtime "^0.13.4"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.14.8" version "7.15.3"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.8.tgz#7119a56f421018852694290b9f9148097391b446" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b"
integrity sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg== integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==
dependencies: dependencies:
regenerator-runtime "^0.13.4" regenerator-runtime "^0.13.4"
@ -2247,6 +2247,11 @@ acorn@^8.0.4:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.0.4.tgz#7a3ae4191466a6984eee0fe3407a4f3aa9db8354" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.0.4.tgz#7a3ae4191466a6984eee0fe3407a4f3aa9db8354"
integrity sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ== integrity sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==
add-zero@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/add-zero/-/add-zero-1.0.0.tgz#88e221696717f66db467672f3f9aa004de9f1a2c"
integrity sha1-iOIhaWcX9m20Z2cvP5qgBN6fGiw=
address@^1.0.1: address@^1.0.1:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6"
@ -5920,6 +5925,14 @@ form-data@~2.3.2:
combined-stream "^1.0.6" combined-stream "^1.0.6"
mime-types "^2.1.12" mime-types "^2.1.12"
format-duration@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/format-duration/-/format-duration-1.4.0.tgz#6ad86c88f504150873cd28ca82d26a26898d9971"
integrity sha512-Mcg3hOAiKxo6JRBgfrQ+sbVvr3D9/4wE7eDQXx3WV2d/yKmrcHXHJS4OhrqVeg+iiFE2Op+pHhdOkQUl8yIclw==
dependencies:
add-zero "^1.0.0"
parse-ms "^1.0.1"
forwarded@~0.1.2: forwarded@~0.1.2:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
@ -9341,6 +9354,11 @@ parse-json@^5.0.0:
json-parse-even-better-errors "^2.3.0" json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6" lines-and-columns "^1.1.6"
parse-ms@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-1.0.1.tgz#56346d4749d78f23430ca0c713850aef91aa361d"
integrity sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=
parse5@5.1.1: parse5@5.1.1:
version "5.1.1" version "5.1.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"

Loading…
Cancel
Save