mirror of
https://github.com/jeffvli/sonixd.git
synced 2026-04-29 10:42:40 -04:00
Add dynamic gradient background for artist page
This commit is contained in:
@@ -260,6 +260,7 @@
|
||||
"electron-redux": "^1.5.4",
|
||||
"electron-settings": "^4.0.2",
|
||||
"electron-updater": "^4.3.4",
|
||||
"fast-average-color": "^7.0.1",
|
||||
"format-duration": "^1.4.0",
|
||||
"history": "^5.0.0",
|
||||
"image-downloader": "^4.0.3",
|
||||
|
||||
@@ -48,7 +48,7 @@ const GenericPage = ({ header, children, hideDivider, ...rest }: any) => {
|
||||
{header}
|
||||
</PageHeader>
|
||||
{!hideDivider && <Divider />}
|
||||
<PageContent id="page-content" padding={rest.padding}>
|
||||
<PageContent id="page-content" padding={rest.padding} $zIndex={rest.contentZIndex}>
|
||||
{children}
|
||||
</PageContent>
|
||||
</PageContainer>
|
||||
|
||||
@@ -153,10 +153,10 @@ export const PageHeader = styled(Header)<{ padding?: string }>`
|
||||
z-index: 1;
|
||||
`;
|
||||
|
||||
export const PageContent = styled(Content)<{ padding?: string }>`
|
||||
export const PageContent = styled(Content)<{ padding?: string; $zIndex?: number }>`
|
||||
position: relative;
|
||||
padding: ${(props) => (props.padding ? props.padding : '10px')};
|
||||
z-index: 1;
|
||||
z-index: ${(props) => props.$zIndex};
|
||||
`;
|
||||
|
||||
// Sidebar.tsx
|
||||
@@ -213,12 +213,16 @@ export const PageHeaderTitle = styled.h1`
|
||||
}
|
||||
`;
|
||||
|
||||
export const PageHeaderWrapper = styled.div<{ $hasImage: boolean; $imageHeight: string }>`
|
||||
display: ${(props) => (props.$hasImage ? 'inline-block' : 'undefined')};
|
||||
width: ${(props) => (props.$hasImage ? `calc(100% - ${props.$imageHeight + 15}px)` : '100%')};
|
||||
margin-left: ${(props) => (props.$hasImage ? '15px' : '0px')};
|
||||
export const PageHeaderWrapper = styled.div<{
|
||||
hasImage: boolean;
|
||||
imageHeight: string;
|
||||
isDark?: boolean;
|
||||
}>`
|
||||
display: ${(props) => (props.hasImage ? 'inline-block' : 'undefined')};
|
||||
width: ${(props) => (props.hasImage ? `calc(100% - ${props.imageHeight + 15}px)` : '100%')};
|
||||
margin-left: ${(props) => (props.hasImage ? '15px' : '0px')};
|
||||
vertical-align: top;
|
||||
color: ${(props) => (props.$hasImage ? '#D8D8D8' : props.theme.colors.layout.page.color)};
|
||||
color: ${(props) => (props.isDark ? '#D8D8D8' : props.theme.colors.layout.page.color)};
|
||||
`;
|
||||
|
||||
export const PageHeaderSubtitleWrapper = styled.span`
|
||||
@@ -228,7 +232,15 @@ export const PageHeaderSubtitleWrapper = styled.span`
|
||||
`;
|
||||
|
||||
export const PageHeaderSubtitleDataLine = styled.div<{ $top?: boolean }>`
|
||||
margin-top: ${(props) => (props.$top ? '0px' : '10px')};
|
||||
margin-top: ${(props) => (props.$top ? '0px' : '7px')};
|
||||
white-space: nowrap;
|
||||
overflow: visible;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
scroll-behavior: smooth;
|
||||
`;
|
||||
|
||||
export const FlatBackground = styled.div<{ $expanded: boolean; $color: string }>`
|
||||
@@ -238,29 +250,29 @@ export const FlatBackground = styled.div<{ $expanded: boolean; $color: string }>
|
||||
height: 200px;
|
||||
position: absolute;
|
||||
width: ${(props) => (props.$expanded ? `calc(100% - 165px)` : 'calc(100% - 56px)')};
|
||||
z-index: 1;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
`;
|
||||
|
||||
export const BlurredBackgroundWrapper = styled.div<{ $expanded: boolean }>`
|
||||
export const BlurredBackgroundWrapper = styled.div<{ expanded: boolean; image: string }>`
|
||||
clip: rect(0, auto, auto, 0);
|
||||
-webkit-clip-path: inset(0 0);
|
||||
clip-path: inset(0 0);
|
||||
position: absolute;
|
||||
left: ${(props) => (props.$expanded ? '165px' : '56px')};
|
||||
width: ${(props) => (props.$expanded ? `calc(100% - 165px)` : 'calc(100% - 56px)')};
|
||||
left: ${(props) => (props.expanded ? '165px' : '56px')};
|
||||
width: ${(props) => (props.expanded ? `calc(100% - 165px)` : 'calc(100% - 56px)')};
|
||||
top: 32px;
|
||||
z-index: 1;
|
||||
display: block;
|
||||
background: #0b0908;
|
||||
background: ${(props) => (props.image ? '#0b0908' : '#00395A')};
|
||||
filter: ${(props) => (props.image ? 'none' : 'brightness(0.3)')};
|
||||
`;
|
||||
|
||||
export const BlurredBackground = styled.img<{ $expanded: boolean; $image: string }>`
|
||||
background-image: ${(props) => `url(${props.$image})`};
|
||||
export const BlurredBackground = styled.img<{ expanded: boolean; image: string }>`
|
||||
background-image: ${(props) => (props.image ? `url(${props.image})` : 'none')};
|
||||
background-position: center 30%;
|
||||
background-size: cover;
|
||||
filter: blur(10px) brightness(0.4);
|
||||
filter: blur(10px) brightness(0.3);
|
||||
|
||||
outline: none !important;
|
||||
border: none !important;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable import/no-cycle */
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import _ from 'lodash';
|
||||
import FastAverageColor from 'fast-average-color';
|
||||
import { shell } from 'electron';
|
||||
import settings from 'electron-settings';
|
||||
import { ButtonToolbar, Whisper, TagGroup } from 'rsuite';
|
||||
@@ -35,9 +36,17 @@ import {
|
||||
setPlayQueue,
|
||||
} from '../../redux/playQueueSlice';
|
||||
import { notifyToast } from '../shared/toast';
|
||||
import { filterPlayQueue, getPlayedSongsNotification, isCached } from '../../shared/utils';
|
||||
import {
|
||||
filterPlayQueue,
|
||||
formatDuration,
|
||||
getPlayedSongsNotification,
|
||||
isCached,
|
||||
} from '../../shared/utils';
|
||||
import { StyledButton, StyledPopover, StyledTag } from '../shared/styled';
|
||||
import { setStatus } from '../../redux/playerSlice';
|
||||
import { GradientBackground, PageHeaderSubtitleDataLine } from '../layout/styled';
|
||||
|
||||
const fac = new FastAverageColor();
|
||||
|
||||
interface ArtistParams {
|
||||
id: string;
|
||||
@@ -50,6 +59,10 @@ const ArtistView = ({ ...rest }: any) => {
|
||||
const misc = useAppSelector((state) => state.misc);
|
||||
const config = useAppSelector((state) => state.config);
|
||||
const [viewType, setViewType] = useState(settings.getSync('albumViewType') || 'list');
|
||||
const [imageAverageColor, setImageAverageColor] = useState({ color: '', loaded: false });
|
||||
const [artistDurationTotal, setArtistDurationTotal] = useState('');
|
||||
const [artistSongTotal, setArtistSongTotal] = useState(0);
|
||||
|
||||
const { id } = useParams<ArtistParams>();
|
||||
const artistId = rest.id ? rest.id : id;
|
||||
const { isLoading, isError, data, error }: any = useQuery(['artist', artistId], () =>
|
||||
@@ -131,18 +144,6 @@ const ArtistView = ({ ...rest }: any) => {
|
||||
notifyToast('info', getPlayedSongsNotification({ ...songs.count, type: 'add' }));
|
||||
};
|
||||
|
||||
if (isLoading || isLoadingAI) {
|
||||
return <PageLoader />;
|
||||
}
|
||||
|
||||
if (isError || isErrorAI) {
|
||||
return (
|
||||
<span>
|
||||
Error: {error?.message} {errorAI?.message}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const handleRowFavorite = async (rowData: any) => {
|
||||
if (!rowData.starred) {
|
||||
await star(rowData.id, 'album');
|
||||
@@ -167,168 +168,248 @@ const ArtistView = ({ ...rest }: any) => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading) {
|
||||
const img = isCached(`${misc.imageCachePath}artist_${data?.id}.jpg`)
|
||||
? `${misc.imageCachePath}artist_${data?.id}.jpg`
|
||||
: data?.image.includes('placeholder')
|
||||
? artistInfo?.largeImageUrl &&
|
||||
!artistInfo?.largeImageUrl?.match('2a96cbd8b46e442fc41c2b86b821562f')
|
||||
? artistInfo?.largeImageUrl
|
||||
: data?.image
|
||||
: data?.image;
|
||||
|
||||
const setAvgColor = (imgUrl: string) => {
|
||||
if (
|
||||
data?.image.match('placeholder') ||
|
||||
(data?.image.match('placeholder') &&
|
||||
artistInfo?.largeImageUrl?.match('2a96cbd8b46e442fc41c2b86b821562f'))
|
||||
) {
|
||||
setImageAverageColor({ color: 'rgba(0, 57, 90, .4)', loaded: true });
|
||||
} else {
|
||||
fac
|
||||
.getColorAsync(imgUrl, {
|
||||
ignoredColor: [
|
||||
[255, 255, 255, 255], // White
|
||||
[0, 0, 0, 255], // Black
|
||||
],
|
||||
mode: 'precision',
|
||||
algorithm: 'dominant',
|
||||
})
|
||||
.then((color) => {
|
||||
return setImageAverageColor({
|
||||
color: color.rgba.replace(',1)', ',0.4)'),
|
||||
loaded: true,
|
||||
});
|
||||
})
|
||||
.catch(() => setAvgColor(imgUrl));
|
||||
}
|
||||
};
|
||||
setAvgColor(img);
|
||||
}
|
||||
}, [artistInfo?.largeImageUrl, data?.id, data?.image, isLoading, misc.imageCachePath]);
|
||||
|
||||
useEffect(() => {
|
||||
const allAlbumDurations = _.sum(_.map(data?.album, 'duration'));
|
||||
const allSongCount = _.sum(_.map(data?.album, 'songCount'));
|
||||
|
||||
setArtistDurationTotal(formatDuration(allAlbumDurations) || 'N/a');
|
||||
setArtistSongTotal(allSongCount);
|
||||
}, [data?.album]);
|
||||
|
||||
if (isLoading || isLoadingAI || imageAverageColor.loaded === false) {
|
||||
return <PageLoader />;
|
||||
}
|
||||
|
||||
if (isError || isErrorAI) {
|
||||
return (
|
||||
<span>
|
||||
Error: {error?.message} {errorAI?.message}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<GenericPage
|
||||
hideDivider
|
||||
header={
|
||||
<GenericPageHeader
|
||||
image={
|
||||
isCached(`${misc.imageCachePath}artist_${data.id}.jpg`)
|
||||
? `${misc.imageCachePath}artist_${data.id}.jpg`
|
||||
: data.image.includes('placeholder')
|
||||
? artistInfo?.largeImageUrl &&
|
||||
!artistInfo?.largeImageUrl?.match('2a96cbd8b46e442fc41c2b86b821562f')
|
||||
? artistInfo.largeImageUrl
|
||||
<>
|
||||
<GradientBackground $expanded={misc.expandSidebar} $color={imageAverageColor.color} />
|
||||
<GenericPage
|
||||
contentZIndex={1}
|
||||
hideDivider
|
||||
header={
|
||||
<GenericPageHeader
|
||||
image={
|
||||
isCached(`${misc.imageCachePath}artist_${data.id}.jpg`)
|
||||
? `${misc.imageCachePath}artist_${data.id}.jpg`
|
||||
: data.image.includes('placeholder')
|
||||
? artistInfo?.largeImageUrl &&
|
||||
!artistInfo?.largeImageUrl?.match('2a96cbd8b46e442fc41c2b86b821562f')
|
||||
? artistInfo.largeImageUrl
|
||||
: data.image
|
||||
: data.image
|
||||
: data.image
|
||||
}
|
||||
cacheImages={{
|
||||
enabled: settings.getSync('cacheImages'),
|
||||
cacheType: 'artist',
|
||||
id: data.id,
|
||||
}}
|
||||
imageHeight={145}
|
||||
title={data.name}
|
||||
showTitleTooltip
|
||||
subtitle={
|
||||
<>
|
||||
<CustomTooltip
|
||||
text={artistInfo?.biography
|
||||
?.replace(/<[^>]*>/, '')
|
||||
.replace('Read more on Last.fm</a>', '')}
|
||||
placement="bottomStart"
|
||||
>
|
||||
<span>
|
||||
{artistInfo?.biography
|
||||
?.replace(/<[^>]*>/, '')
|
||||
.replace('Read more on Last.fm</a>', '')
|
||||
?.trim()
|
||||
? `${artistInfo?.biography
|
||||
?.replace(/<[^>]*>/, '')
|
||||
.replace('Read more on Last.fm</a>', '')}`
|
||||
: 'No artist biography found'}
|
||||
</span>
|
||||
</CustomTooltip>
|
||||
<div style={{ marginTop: '10px' }}>
|
||||
<ButtonToolbar>
|
||||
<PlayButton appearance="primary" size="md" onClick={handlePlay} />
|
||||
<PlayAppendNextButton
|
||||
appearance="primary"
|
||||
size="md"
|
||||
onClick={() => handlePlayAppend('next')}
|
||||
/>
|
||||
<PlayAppendButton
|
||||
appearance="primary"
|
||||
size="md"
|
||||
onClick={() => handlePlayAppend('later')}
|
||||
/>
|
||||
<FavoriteButton size="md" isFavorite={data.starred} onClick={handleFavorite} />
|
||||
<Whisper
|
||||
placement="auto"
|
||||
trigger="hover"
|
||||
enterable
|
||||
speaker={
|
||||
<StyledPopover style={{ width: '400px' }}>
|
||||
<div>
|
||||
<h6>Related artists</h6>
|
||||
<TagGroup>
|
||||
{artistInfo.similarArtist?.map((artist: any) => (
|
||||
<StyledTag
|
||||
key={artist.id}
|
||||
onClick={() => {
|
||||
if (!rest.isModal) {
|
||||
history.push(`/library/artist/${artist.id}`);
|
||||
} else {
|
||||
dispatch(
|
||||
addModalPage({
|
||||
pageType: 'artist',
|
||||
id: artist.id,
|
||||
})
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{artist.name}
|
||||
</StyledTag>
|
||||
))}
|
||||
</TagGroup>
|
||||
</div>
|
||||
<br />
|
||||
<StyledButton
|
||||
appearance="primary"
|
||||
disabled={!artistInfo?.lastFmUrl}
|
||||
onClick={() => shell.openExternal(artistInfo?.lastFmUrl)}
|
||||
>
|
||||
View on Last.FM
|
||||
</StyledButton>
|
||||
</StyledPopover>
|
||||
}
|
||||
>
|
||||
<StyledButton size="md">Info</StyledButton>
|
||||
</Whisper>
|
||||
</ButtonToolbar>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
searchQuery={searchQuery}
|
||||
handleSearch={(e: any) => setSearchQuery(e)}
|
||||
clearSearchQuery={() => setSearchQuery('')}
|
||||
showSearchBar
|
||||
showViewTypeButtons
|
||||
viewTypeSetting="album"
|
||||
handleListClick={() => setViewType('list')}
|
||||
handleGridClick={() => setViewType('grid')}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<>
|
||||
{viewType === 'list' && (
|
||||
<ListViewType
|
||||
data={searchQuery !== '' ? filteredData : data.album}
|
||||
tableColumns={config.lookAndFeel.listView.album.columns}
|
||||
handleRowClick={handleRowClick}
|
||||
handleRowDoubleClick={handleRowDoubleClick}
|
||||
virtualized
|
||||
rowHeight={config.lookAndFeel.listView.album.rowHeight}
|
||||
fontSize={config.lookAndFeel.listView.album.fontSize}
|
||||
}
|
||||
cacheImages={{
|
||||
enabled: settings.getSync('cacheImages'),
|
||||
cacheType: 'album',
|
||||
cacheIdProperty: 'albumId',
|
||||
cacheType: 'artist',
|
||||
id: data.id,
|
||||
}}
|
||||
listType="album"
|
||||
isModal={rest.isModal}
|
||||
disabledContextMenuOptions={[
|
||||
'removeSelected',
|
||||
'moveSelectedTo',
|
||||
'deletePlaylist',
|
||||
'viewInFolder',
|
||||
]}
|
||||
handleFavorite={handleRowFavorite}
|
||||
/>
|
||||
)}
|
||||
imageHeight={185}
|
||||
title={data.name}
|
||||
showTitleTooltip
|
||||
subtitle={
|
||||
<>
|
||||
<PageHeaderSubtitleDataLine $top>
|
||||
<strong>ARTIST</strong> • {data.albumCount} albums • {artistSongTotal} songs •{' '}
|
||||
{artistDurationTotal}
|
||||
</PageHeaderSubtitleDataLine>
|
||||
<PageHeaderSubtitleDataLine
|
||||
style={{
|
||||
minHeight: '2.5rem',
|
||||
maxHeight: '2.5rem',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'pre-wrap',
|
||||
}}
|
||||
>
|
||||
<CustomTooltip
|
||||
text={artistInfo?.biography
|
||||
?.replace(/<[^>]*>/, '')
|
||||
.replace('Read more on Last.fm</a>', '')}
|
||||
placement="bottomStart"
|
||||
>
|
||||
<span>
|
||||
{artistInfo?.biography
|
||||
?.replace(/<[^>]*>/, '')
|
||||
.replace('Read more on Last.fm</a>', '')
|
||||
?.trim()
|
||||
? `${artistInfo?.biography
|
||||
?.replace(/<[^>]*>/, '')
|
||||
.replace('Read more on Last.fm</a>', '')}`
|
||||
: 'No artist biography found'}
|
||||
</span>
|
||||
</CustomTooltip>
|
||||
</PageHeaderSubtitleDataLine>
|
||||
|
||||
{viewType === 'grid' && (
|
||||
<GridViewType
|
||||
data={searchQuery === '' ? data.album : filteredData}
|
||||
cardTitle={{
|
||||
prefix: '/library/album',
|
||||
property: 'name',
|
||||
urlProperty: 'albumId',
|
||||
}}
|
||||
cardSubtitle={{
|
||||
property: 'songCount',
|
||||
unit: ' tracks',
|
||||
}}
|
||||
playClick={{ type: 'album', idProperty: 'id' }}
|
||||
size={config.lookAndFeel.gridView.cardSize}
|
||||
cacheType="album"
|
||||
isModal={rest.isModal}
|
||||
handleFavorite={handleRowFavorite}
|
||||
<div style={{ marginTop: '10px' }}>
|
||||
<ButtonToolbar>
|
||||
<PlayButton appearance="primary" size="lg" onClick={handlePlay} />
|
||||
<PlayAppendNextButton
|
||||
appearance="primary"
|
||||
size="lg"
|
||||
onClick={() => handlePlayAppend('next')}
|
||||
/>
|
||||
<PlayAppendButton
|
||||
appearance="primary"
|
||||
size="lg"
|
||||
onClick={() => handlePlayAppend('later')}
|
||||
/>
|
||||
<FavoriteButton size="lg" isFavorite={data.starred} onClick={handleFavorite} />
|
||||
<Whisper
|
||||
placement="auto"
|
||||
trigger="hover"
|
||||
enterable
|
||||
speaker={
|
||||
<StyledPopover style={{ width: '400px' }}>
|
||||
<div>
|
||||
<h6>Related artists</h6>
|
||||
<TagGroup>
|
||||
{artistInfo.similarArtist?.map((artist: any) => (
|
||||
<StyledTag
|
||||
key={artist.id}
|
||||
onClick={() => {
|
||||
if (!rest.isModal) {
|
||||
history.push(`/library/artist/${artist.id}`);
|
||||
} else {
|
||||
dispatch(
|
||||
addModalPage({
|
||||
pageType: 'artist',
|
||||
id: artist.id,
|
||||
})
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{artist.name}
|
||||
</StyledTag>
|
||||
))}
|
||||
</TagGroup>
|
||||
</div>
|
||||
<br />
|
||||
<StyledButton
|
||||
appearance="primary"
|
||||
disabled={!artistInfo?.lastFmUrl}
|
||||
onClick={() => shell.openExternal(artistInfo?.lastFmUrl)}
|
||||
>
|
||||
View on Last.FM
|
||||
</StyledButton>
|
||||
</StyledPopover>
|
||||
}
|
||||
>
|
||||
<StyledButton size="lg">Info</StyledButton>
|
||||
</Whisper>
|
||||
</ButtonToolbar>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
searchQuery={searchQuery}
|
||||
handleSearch={(e: any) => setSearchQuery(e)}
|
||||
clearSearchQuery={() => setSearchQuery('')}
|
||||
showSearchBar
|
||||
showViewTypeButtons
|
||||
viewTypeSetting="album"
|
||||
handleListClick={() => setViewType('list')}
|
||||
handleGridClick={() => setViewType('grid')}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</GenericPage>
|
||||
}
|
||||
>
|
||||
<>
|
||||
{viewType === 'list' && (
|
||||
<ListViewType
|
||||
data={searchQuery !== '' ? filteredData : data.album}
|
||||
tableColumns={config.lookAndFeel.listView.album.columns}
|
||||
handleRowClick={handleRowClick}
|
||||
handleRowDoubleClick={handleRowDoubleClick}
|
||||
virtualized
|
||||
rowHeight={config.lookAndFeel.listView.album.rowHeight}
|
||||
fontSize={config.lookAndFeel.listView.album.fontSize}
|
||||
cacheImages={{
|
||||
enabled: settings.getSync('cacheImages'),
|
||||
cacheType: 'album',
|
||||
cacheIdProperty: 'albumId',
|
||||
}}
|
||||
listType="album"
|
||||
isModal={rest.isModal}
|
||||
disabledContextMenuOptions={[
|
||||
'removeSelected',
|
||||
'moveSelectedTo',
|
||||
'deletePlaylist',
|
||||
'viewInFolder',
|
||||
]}
|
||||
handleFavorite={handleRowFavorite}
|
||||
/>
|
||||
)}
|
||||
|
||||
{viewType === 'grid' && (
|
||||
<GridViewType
|
||||
data={searchQuery === '' ? data.album : filteredData}
|
||||
cardTitle={{
|
||||
prefix: '/library/album',
|
||||
property: 'name',
|
||||
urlProperty: 'albumId',
|
||||
}}
|
||||
cardSubtitle={{
|
||||
property: 'songCount',
|
||||
unit: ' tracks',
|
||||
}}
|
||||
playClick={{ type: 'album', idProperty: 'id' }}
|
||||
size={config.lookAndFeel.gridView.cardSize}
|
||||
cacheType="album"
|
||||
isModal={rest.isModal}
|
||||
handleFavorite={handleRowFavorite}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</GenericPage>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
23
yarn.lock
23
yarn.lock
@@ -1375,14 +1375,7 @@
|
||||
"@types/yargs" "^15.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@malept/cross-spawn-promise@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.0.tgz#258fde4098f5004a56db67c35f33033af64810f6"
|
||||
integrity sha512-GeIK5rfU1Yd7BZJQPTGZMMmcZy5nhRToPXZcjaDwQDRSewdhp648GT2E4dh+L7+Io7AOW6WQ+GR44QSzja4qxg==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.1"
|
||||
|
||||
"@malept/cross-spawn-promise@^1.1.1":
|
||||
"@malept/cross-spawn-promise@^1.1.0", "@malept/cross-spawn-promise@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d"
|
||||
integrity sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==
|
||||
@@ -1766,6 +1759,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
|
||||
integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
|
||||
|
||||
"@types/offscreencanvas@^2019.6.4":
|
||||
version "2019.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.6.4.tgz#64f6d120b53925028299c744fcdd32d2cd525963"
|
||||
integrity sha512-u8SAgdZ8ROtkTF+mfZGOscl0or6BSj9A4g37e6nvxDc+YB/oDut0wHkK2PBBiC2bNR8TS0CPV+1gAk4fNisr1Q==
|
||||
|
||||
"@types/parse-json@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||
@@ -5722,6 +5720,13 @@ extsprintf@^1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
|
||||
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
|
||||
|
||||
fast-average-color@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fast-average-color/-/fast-average-color-7.0.1.tgz#2304cc62578f4427c1bc48844faa1c5178835b67"
|
||||
integrity sha512-M9Lg7mO/sSGezi7cB/i+I9ym33IBcdeREHk222//3sbtj2+Aq9Cv3DIVY1asn3fu4rX2ENQ2iv2mCSaVpC68SQ==
|
||||
dependencies:
|
||||
"@types/offscreencanvas" "^2019.6.4"
|
||||
|
||||
fast-deep-equal@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
|
||||
@@ -11396,7 +11401,7 @@ source-map-resolve@^0.6.0:
|
||||
atob "^2.1.2"
|
||||
decode-uri-component "^0.2.0"
|
||||
|
||||
source-map-support@^0.5.11, source-map-support@^0.5.16, source-map-support@^0.5.19, source-map-support@^0.5.6, source-map-support@~0.5.19:
|
||||
source-map-support@^0.5.16, source-map-support@^0.5.19, source-map-support@^0.5.6, source-map-support@~0.5.19:
|
||||
version "0.5.20"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
|
||||
integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
|
||||
|
||||
Reference in New Issue
Block a user