Browse Source

Improvements to album page

- Link to album list
- Album artist specified
- Genres separated from artists
- Mouse wheel horizontal scroll
- Add link wrapper to enforce link max width
master
jeffvli 3 years ago
committed by Jeff
parent
commit
d5e59f9975
  1. 4
      src/components/layout/styled.tsx
  2. 132
      src/components/library/AlbumView.tsx
  3. 16
      src/components/shared/styled.ts

4
src/components/layout/styled.tsx

@ -242,10 +242,10 @@ export const PageHeaderSubtitleWrapper = styled.span`
font-size: 14px; font-size: 14px;
`; `;
export const PageHeaderSubtitleDataLine = styled.div<{ $top?: boolean }>` export const PageHeaderSubtitleDataLine = styled.div<{ $top?: boolean; $overflow?: boolean }>`
margin-top: ${(props) => (props.$top ? '0px' : '7px')}; margin-top: ${(props) => (props.$top ? '0px' : '7px')};
white-space: nowrap; white-space: nowrap;
overflow: auto; overflow: ${(props) => (props.$overflow ? 'visible' : 'auto')};
::-webkit-scrollbar { ::-webkit-scrollbar {
height: 4px; height: 4px;

132
src/components/library/AlbumView.tsx

@ -1,4 +1,4 @@
import React from 'react'; import React, { useRef } from 'react';
import _ from 'lodash'; import _ from 'lodash';
import { nanoid } from 'nanoid/non-secure'; import { nanoid } from 'nanoid/non-secure';
import { clipboard, shell } from 'electron'; import { clipboard, shell } from 'electron';
@ -45,7 +45,13 @@ import {
getPlayedSongsNotification, getPlayedSongsNotification,
isCached, isCached,
} from '../../shared/utils'; } from '../../shared/utils';
import { StyledButton, StyledPopover, StyledTagLink } from '../shared/styled'; import {
LinkWrapper,
StyledButton,
StyledLink,
StyledPopover,
StyledTagLink,
} from '../shared/styled';
import { setActive } from '../../redux/albumSlice'; import { setActive } from '../../redux/albumSlice';
import { import {
BlurredBackground, BlurredBackground,
@ -67,6 +73,8 @@ const AlbumView = ({ ...rest }: any) => {
const config = useAppSelector((state) => state.config); const config = useAppSelector((state) => state.config);
const history = useHistory(); const history = useHistory();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const artistLineRef = useRef<any>();
const genreLineRef = useRef<any>();
const { id } = useParams<AlbumParams>(); const { id } = useParams<AlbumParams>();
const albumId = rest.id ? rest.id : id; const albumId = rest.id ? rest.id : id;
@ -319,8 +327,21 @@ const AlbumView = ({ ...rest }: any) => {
showTitleTooltip showTitleTooltip
subtitle={ subtitle={
<div> <div>
<PageHeaderSubtitleDataLine $top> <PageHeaderSubtitleDataLine $top $overflow>
<strong>ALBUM</strong> {data.songCount} songs {formatDuration(data.duration)} <StyledLink onClick={() => history.push('/library/album')}>ALBUM</StyledLink>{' '}
{data.albumArtist && (
<>
by{' '}
<LinkWrapper maxWidth="20vw">
<StyledLink
onClick={() => history.push(`/library/artist/${data.albumArtistId}`)}
>
<strong>{data.albumArtist}</strong>
</StyledLink>
</LinkWrapper>
</>
)}{' '}
{data.songCount} songs, {formatDuration(data.duration)}
{data.year && ( {data.year && (
<> <>
{' • '} {' • '}
@ -328,49 +349,73 @@ const AlbumView = ({ ...rest }: any) => {
</> </>
)} )}
</PageHeaderSubtitleDataLine> </PageHeaderSubtitleDataLine>
<PageHeaderSubtitleDataLine> <PageHeaderSubtitleDataLine
ref={genreLineRef}
onWheel={(e: any) => {
if (!e.shiftKey) {
if (e.deltaY === 0) return;
const position = genreLineRef.current.scrollLeft;
genreLineRef.current.scrollTo({
top: 0,
left: position + e.deltaY,
behavior: 'smooth',
});
}
}}
>
Added {formatDate(data.created)} Added {formatDate(data.created)}
</PageHeaderSubtitleDataLine> {data.genre.map((d: Genre, i: number) => {
<PageHeaderSubtitleDataLine>
{data.artist.map((d: Artist) => {
return ( return (
<StyledTagLink <>
{i === 0 && ' • '}
{i > 0 && ', '}
<LinkWrapper maxWidth="13vw">
<StyledLink
key={nanoid()} key={nanoid()}
tabIndex={0} tabIndex={0}
tooltip={d.title}
onClick={() => { onClick={() => {
if (!rest.isModal) { if (!rest.isModal) {
history.push(`/library/artist/${d.id}`); dispatch(setActive({ ...album.active, filter: d.title }));
} else { setTimeout(() => {
dispatch( history.push(`/library/album?sortType=${d.title}`);
addModalPage({ }, 50);
pageType: 'artist',
id: d.id,
})
);
} }
}} }}
onKeyDown={(e: any) => { onKeyDown={(e: any) => {
if (e.key === ' ' || e.key === 'Enter') { if (e.key === ' ' || e.key === 'Enter') {
e.preventDefault(); e.preventDefault();
if (!rest.isModal) { if (!rest.isModal) {
history.push(`/library/artist/${d.id}`); dispatch(setActive({ ...album.active, filter: d.title }));
} else { setTimeout(() => {
dispatch( history.push(`/library/album?sortType=${d.title}`);
addModalPage({ }, 50);
pageType: 'artist',
id: d.id,
})
);
} }
} }
}} }}
> >
{d.title} {d.title}
</StyledTagLink> </StyledLink>
</LinkWrapper>
</>
); );
})} })}
{data.genre.map((d: Genre) => { </PageHeaderSubtitleDataLine>
<PageHeaderSubtitleDataLine
ref={artistLineRef}
onWheel={(e: any) => {
if (!e.shiftKey) {
if (e.deltaY === 0) return;
const position = artistLineRef.current.scrollLeft;
artistLineRef.current.scrollTo({
top: 0,
left: position + e.deltaY,
behavior: 'smooth',
});
}
}}
>
{data.artist ? (
data.artist.map((d: Artist) => {
return ( return (
<StyledTagLink <StyledTagLink
key={nanoid()} key={nanoid()}
@ -378,20 +423,28 @@ const AlbumView = ({ ...rest }: any) => {
tooltip={d.title} tooltip={d.title}
onClick={() => { onClick={() => {
if (!rest.isModal) { if (!rest.isModal) {
dispatch(setActive({ ...album.active, filter: d.title })); history.push(`/library/artist/${d.id}`);
setTimeout(() => { } else {
history.push(`/library/album?sortType=${d.title}`); dispatch(
}, 50); addModalPage({
pageType: 'artist',
id: d.id,
})
);
} }
}} }}
onKeyDown={(e: any) => { onKeyDown={(e: any) => {
if (e.key === ' ' || e.key === 'Enter') { if (e.key === ' ' || e.key === 'Enter') {
e.preventDefault(); e.preventDefault();
if (!rest.isModal) { if (!rest.isModal) {
dispatch(setActive({ ...album.active, filter: d.title })); history.push(`/library/artist/${d.id}`);
setTimeout(() => { } else {
history.push(`/library/album?sortType=${d.title}`); dispatch(
}, 50); addModalPage({
pageType: 'artist',
id: d.id,
})
);
} }
} }
}} }}
@ -399,7 +452,10 @@ const AlbumView = ({ ...rest }: any) => {
{d.title} {d.title}
</StyledTagLink> </StyledTagLink>
); );
})} })
) : (
<span>&#8203;</span>
)}
</PageHeaderSubtitleDataLine> </PageHeaderSubtitleDataLine>
<div style={{ marginTop: '10px' }}> <div style={{ marginTop: '10px' }}>
<ButtonToolbar> <ButtonToolbar>
@ -445,7 +501,7 @@ const AlbumView = ({ ...rest }: any) => {
> >
<ListViewType <ListViewType
data={misc.searchQuery !== '' ? filteredData : data.song} data={misc.searchQuery !== '' ? filteredData : data.song}
tableColumns={settings.getSync('musicListColumns')} tableColumns={config.lookAndFeel.listView.music.columns}
handleRowClick={handleRowClick} handleRowClick={handleRowClick}
handleRowDoubleClick={handleRowDoubleClick} handleRowDoubleClick={handleRowDoubleClick}
handleRating={handleRowRating} handleRating={handleRowRating}

16
src/components/shared/styled.ts

@ -470,13 +470,23 @@ export const SectionTitle = styled.a`
} }
`; `;
export const StyledLink = styled.a` export const LinkWrapper = styled.span<{ maxWidth: string }>`
display: inline-block;
max-width: ${(props) => props.maxWidth};
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: bottom;
`;
export const StyledLink = styled.a<{ underline?: boolean }>`
color: ${(props) => props.theme.colors.layout.page.color}; color: ${(props) => props.theme.colors.layout.page.color};
cursor: pointer; cursor: pointer;
text-decoration: underline; text-decoration: ${(props) => (props.underline ? 'underline' : undefined)};
font-weight: bold;
&:hover { &:hover {
color: ${(props) => props.theme.colors.button.link.colorHover}; color: ${(props) => props.theme.colors.layout.page.color};
} }
&:focus-visible { &:focus-visible {

Loading…
Cancel
Save