Skip to content

Commit b076f56

Browse files
committed
feat: Add favicon files and enhance PillControlBar styles for dark mode
- Introduced new favicon.ico and favicon.png files for improved branding. - Updated the PillControlBar component to adjust text color based on dark mode, ensuring better visibility and user experience. - Refactored styles in the MiniPlayer and StandardPlayer components to enhance layout and responsiveness. - Added new hooks and logic for the StandardPlayer mobile and web components to streamline functionality and improve maintainability.
1 parent 1fbfab1 commit b076f56

File tree

16 files changed

+717
-484
lines changed

16 files changed

+717
-484
lines changed

public/favicon.ico

4.19 KB
Binary file not shown.

public/favicon.png

15.1 KB
Loading

src/shared-components/molecules/PillControlBar.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export const PillControlBar = ({
7979
onClick={onToggleNarration}
8080
aria-label="Toggle Narration"
8181
variant="transparent"
82-
style={{ color: isNarrationEnabled ? theme.black : theme.colors.gray[6] }}
82+
style={{ color: isNarrationEnabled ? (isDark ? theme.white : theme.black) : theme.colors.gray[6] }}
8383
size="sm"
8484
>
8585
<LuHeadphones size={16} />
@@ -107,7 +107,7 @@ export const PillControlBar = ({
107107
onClick={onToggleMusic}
108108
aria-label="Toggle Music"
109109
variant="transparent"
110-
style={{ color: isMusicEnabled ? theme.black : theme.colors.gray[6] }}
110+
style={{ color: isMusicEnabled ? (isDark ? theme.white : theme.black) : theme.colors.gray[6] }}
111111
size="sm"
112112
>
113113
<LuMusic size={16} />
@@ -130,7 +130,7 @@ export const PillControlBar = ({
130130
borderRight: `1px solid ${dividerColor}`,
131131
}}
132132
>
133-
<ActionIcon variant="transparent" onClick={onPlaylistClick} aria-label="Playlist" style={{ color: theme.black }}>
133+
<ActionIcon variant="transparent" onClick={onPlaylistClick} aria-label="Playlist" style={{ color: isDark ? theme.white : theme.black }}>
134134
<LuListMusic size={18} />
135135
</ActionIcon>
136136
</Box>
@@ -142,7 +142,7 @@ export const PillControlBar = ({
142142
borderRadius: '0 9999px 9999px 0',
143143
}}
144144
>
145-
<ActionIcon variant="transparent" onClick={onMinimizeClick} aria-label="Minimize" style={{ color: theme.black }}>
145+
<ActionIcon variant="transparent" onClick={onMinimizeClick} aria-label="Minimize" style={{ color: isDark ? theme.white : theme.black }}>
146146
<LuChevronDown size={18} />
147147
</ActionIcon>
148148
</Box>

src/shared-components/organisms/Footer/components/MiniPlayer/MiniPlayer.styles.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import { rem } from '@mantine/core';
44
export const MiniPlayerContainer = styled.div`
55
display: flex;
66
flex-direction: column;
7-
height: 100%;
87
justify-content: center;
98
width: 100%;
9+
background-color: ${({ theme }) => theme.colors.dark[8]};
10+
padding-bottom: env(safe-area-inset-bottom, 0px);
1011
`;
1112

1213
export const MiniPlayerTopRow = styled.div`
@@ -15,12 +16,14 @@ export const MiniPlayerTopRow = styled.div`
1516
justify-content: space-between;
1617
width: 100%;
1718
padding-top: ${rem(8)};
19+
min-height: 0;
1820
1921
@media (max-width: ${({ theme }) => theme.breakpoints.sm}) {
2022
flex-direction: row;
2123
align-items: center;
2224
justify-content: space-between;
2325
padding-top: ${rem(8)};
26+
min-height: 0;
2427
}
2528
`;
2629

@@ -48,12 +51,14 @@ export const MiniPlayerProgressBar = styled.div`
4851
margin-top: ${rem(4)};
4952
display: flex;
5053
align-items: center;
54+
min-height: 0;
5155
5256
@media (min-width: ${({ theme }) => theme.breakpoints.sm}) {
5357
margin-top: 0;
5458
margin-left: ${rem(16)};
5559
width: auto;
5660
flex: 1 1 0%;
5761
max-width: none;
62+
min-height: 0;
5863
}
5964
`;
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { useCallback, useRef, useEffect, useState } from 'react';
2+
import { useMantineTheme } from '@mantine/core';
3+
import { StandardPlayerProps } from './StandardPlayer.types';
4+
5+
export function useStandardPlayerMobile(props: StandardPlayerProps) {
6+
const progressBarContainerRef = useRef<HTMLDivElement>(null);
7+
const theme = useMantineTheme();
8+
const [controlMode, setControlMode] = useState<'music' | 'narration'>(props.isMusicEnabled ? 'music' : 'narration');
9+
10+
useEffect(() => {
11+
if (props.isMusicEnabled && props.isNarrationEnabled) return;
12+
if (props.isMusicEnabled) setControlMode('music');
13+
else if (props.isNarrationEnabled) setControlMode('narration');
14+
}, [props.isMusicEnabled, props.isNarrationEnabled]);
15+
16+
const showToggle = props.isMusicEnabled && props.isNarrationEnabled;
17+
const toggleControlMode = () => {
18+
setControlMode((prev) => (prev === 'narration' ? 'music' : 'narration'));
19+
};
20+
21+
// Always allow arrows if there is a music track
22+
const isMusicTrackAvailable = !!props.currentTrack;
23+
const isEffectivelyPlaying = props.isMusicPlaying || props.isVoicePlaying;
24+
const isNarrationActive = controlMode === 'narration';
25+
const displayControlTrack = controlMode === 'music' ? props.currentTrack : props.activeVoiceTrack;
26+
const displayCurrentTime = controlMode === 'music' ? props.currentTime : props.voiceCurrentTime;
27+
const displayDuration = controlMode === 'music' ? props.duration : props.voiceDuration;
28+
const displayTrackAvailable = !!displayControlTrack;
29+
30+
const handlePlayPause = () => {
31+
props.startUserInteraction?.();
32+
if (props.isMusicEnabled && props.isNarrationEnabled) {
33+
props.onPlayToggle();
34+
props.onPlayToggle();
35+
} else {
36+
props.onPlayToggle();
37+
}
38+
};
39+
40+
const handleProgressBarClick = useCallback((event: React.MouseEvent<HTMLDivElement>) => {
41+
if (!progressBarContainerRef.current || displayDuration <= 0) return;
42+
props.startUserInteraction?.();
43+
const rect = progressBarContainerRef.current.getBoundingClientRect();
44+
const clickX = event.clientX - rect.left;
45+
const containerWidth = rect.width;
46+
const newProgress = (clickX / containerWidth) * 100;
47+
if (controlMode === 'music') {
48+
props.onSeekMusic(Math.max(0, Math.min(100, newProgress)));
49+
} else if (controlMode === 'narration') {
50+
props.onSeekNarration(Math.max(0, Math.min(100, newProgress)));
51+
}
52+
}, [displayDuration, props.onSeekMusic, props.onSeekNarration, controlMode, props.startUserInteraction]);
53+
54+
// Always use music playlist navigation for arrows
55+
const handlePrevTrack = () => {
56+
props.startUserInteraction?.();
57+
props.onPrevTrack();
58+
};
59+
const handleNextTrack = () => {
60+
props.startUserInteraction?.();
61+
props.onNextTrack();
62+
};
63+
64+
return {
65+
theme,
66+
progressBarContainerRef,
67+
controlMode,
68+
setControlMode,
69+
showToggle,
70+
toggleControlMode,
71+
isEffectivelyPlaying,
72+
isNarrationActive,
73+
displayControlTrack,
74+
displayCurrentTime,
75+
displayDuration,
76+
displayTrackAvailable,
77+
handlePlayPause,
78+
handleProgressBarClick,
79+
handlePrevTrack,
80+
handleNextTrack,
81+
isMusicTrackAvailable,
82+
};
83+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { StandardPlayerProps } from './StandardPlayer.types';
2+
3+
export function getDisplayTitle(controlMode: 'music' | 'narration', isMusicEnabled: boolean, isNarrationEnabled: boolean, activeMusicTrack: any, activeVoiceTrack: any) {
4+
if (controlMode === 'narration') {
5+
if (isMusicEnabled && isNarrationEnabled && activeMusicTrack?.title) {
6+
return `Narration + ${activeMusicTrack.title}`;
7+
} else {
8+
return 'Narration';
9+
}
10+
} else if (controlMode === 'music' && activeMusicTrack?.title) {
11+
return activeMusicTrack.title;
12+
} else {
13+
return 'Audio Player';
14+
}
15+
}
16+
17+
export function getDisplayArtist(isMusicEnabled: boolean, isNarrationEnabled: boolean, activeMusicTrack: any, activeVoiceTrack: any) {
18+
return isMusicEnabled && isNarrationEnabled && activeVoiceTrack && activeMusicTrack
19+
? 'Narration and Music by David Mieloch'
20+
: isNarrationEnabled && activeVoiceTrack
21+
? 'Narration by David Mieloch'
22+
: activeMusicTrack?.artist || 'Music by David Mieloch';
23+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { MantineTheme } from '@mantine/core';
2+
import { CSSProperties } from 'react';
3+
4+
export const getPlayerContainerStyle = (): CSSProperties => ({
5+
height: 'auto',
6+
minHeight: '110px',
7+
width: '100%',
8+
padding: '8px 12px',
9+
});
10+
11+
export const getArtworkBoxStyle = (artworkSize: number): CSSProperties => ({
12+
height: 'auto',
13+
width: `${artworkSize + 10}px`,
14+
flexShrink: 0,
15+
});
16+
17+
export const getToggleButtonBoxStyle = (): CSSProperties => ({
18+
width: '100%',
19+
display: 'flex',
20+
justifyContent: 'center',
21+
margin: '8px 0',
22+
});
23+
24+
export const getMetaTextStyle = (color: string): CSSProperties => ({
25+
color,
26+
});
27+
28+
export const getProgressBarBoxStyle = (): CSSProperties => ({
29+
width: '100%',
30+
padding: '0 8px',
31+
});
32+
33+
export const getProgressBarContainerStyle = (): CSSProperties => ({
34+
flexGrow: 1,
35+
cursor: 'pointer',
36+
padding: '8px 0',
37+
margin: '-8px 0',
38+
});
39+
40+
export const getTimeTextStyle = (align: 'right' | 'left'): CSSProperties => ({
41+
whiteSpace: 'nowrap',
42+
width: 35,
43+
textAlign: align,
44+
});
45+
46+
export const getEmptyBarStyle = (colors: any): CSSProperties => ({
47+
width: '100%',
48+
height: '4px',
49+
backgroundColor: colors.progressBackground,
50+
borderRadius: '2px',
51+
marginTop: '4px',
52+
});
53+
54+
export const getButtonStyles = (): CSSProperties => ({
55+
border: '1px solid black',
56+
backgroundColor: 'white',
57+
color: 'black',
58+
borderRadius: '20px',
59+
});
60+
61+
export const getBottomRowStyle = (): CSSProperties => ({
62+
width: '100%',
63+
marginTop: '8px',
64+
});

0 commit comments

Comments
 (0)