add explicit blurring to left expanded image and full screen (#1701)

* add explicit blurring to left expanded image and full screen
This commit is contained in:
Kendall Garner
2026-02-13 02:49:57 +00:00
committed by GitHub
parent f487560ec5
commit 78875572e9
4 changed files with 49 additions and 6 deletions
@@ -6,6 +6,10 @@
filter: drop-shadow(0 0 5px rgb(0 0 0 / 40%)) drop-shadow(0 0 5px rgb(0 0 0 / 40%)); filter: drop-shadow(0 0 5px rgb(0 0 0 / 40%)) drop-shadow(0 0 5px rgb(0 0 0 / 40%));
} }
.censored.image {
filter: blur(30px);
}
.image-container { .image-container {
position: relative; position: relative;
display: flex; display: flex;
@@ -11,7 +11,12 @@ import {
useRadioPlayer, useRadioPlayer,
} from '/@/renderer/features/radio/hooks/use-radio-player'; } from '/@/renderer/features/radio/hooks/use-radio-player';
import { AppRoute } from '/@/renderer/router/routes'; import { AppRoute } from '/@/renderer/router/routes';
import { useNativeAspectRatio, usePlayerData, usePlayerSong } from '/@/renderer/store'; import {
useGeneralSettings,
useNativeAspectRatio,
usePlayerData,
usePlayerSong,
} from '/@/renderer/store';
import { Badge } from '/@/shared/components/badge/badge'; import { Badge } from '/@/shared/components/badge/badge';
import { Center } from '/@/shared/components/center/center'; import { Center } from '/@/shared/components/center/center';
import { Flex } from '/@/shared/components/flex/flex'; import { Flex } from '/@/shared/components/flex/flex';
@@ -20,7 +25,7 @@ import { Icon } from '/@/shared/components/icon/icon';
import { Stack } from '/@/shared/components/stack/stack'; import { Stack } from '/@/shared/components/stack/stack';
import { Text } from '/@/shared/components/text/text'; import { Text } from '/@/shared/components/text/text';
import { useSetState } from '/@/shared/hooks/use-set-state'; import { useSetState } from '/@/shared/hooks/use-set-state';
import { LibraryItem } from '/@/shared/types/domain-types'; import { ExplicitStatus, LibraryItem } from '/@/shared/types/domain-types';
const imageVariants: Variants = { const imageVariants: Variants = {
closed: { closed: {
@@ -49,9 +54,14 @@ const MotionImage = motion.img;
const ImageWithPlaceholder = ({ const ImageWithPlaceholder = ({
className, className,
explicit,
placeholderIcon = 'itemAlbum', placeholderIcon = 'itemAlbum',
...props ...props
}: HTMLMotionProps<'img'> & { placeholder?: string; placeholderIcon?: 'itemAlbum' | 'radio' }) => { }: HTMLMotionProps<'img'> & {
explicit?: boolean;
placeholder?: string;
placeholderIcon?: 'itemAlbum' | 'radio';
}) => {
const nativeAspectRatio = useNativeAspectRatio(); const nativeAspectRatio = useNativeAspectRatio();
if (!props.src) { if (!props.src) {
@@ -71,7 +81,9 @@ const ImageWithPlaceholder = ({
return ( return (
<MotionImage <MotionImage
className={clsx(styles.image, className)} className={clsx(styles.image, className, {
[styles.censored]: explicit,
})}
style={{ style={{
objectFit: nativeAspectRatio ? 'contain' : 'cover', objectFit: nativeAspectRatio ? 'contain' : 'cover',
width: nativeAspectRatio ? 'auto' : '100%', width: nativeAspectRatio ? 'auto' : '100%',
@@ -89,6 +101,7 @@ export const FullScreenPlayerImage = () => {
const currentSong = usePlayerSong(); const currentSong = usePlayerSong();
const { nextSong } = usePlayerData(); const { nextSong } = usePlayerData();
const { blurExplicitImages } = useGeneralSettings();
const isPlayingRadio = isRadioActive && isRadioPlaying; const isPlayingRadio = isRadioActive && isRadioPlaying;
@@ -107,8 +120,10 @@ export const FullScreenPlayerImage = () => {
}); });
const [imageState, setImageState] = useSetState({ const [imageState, setImageState] = useSetState({
bottomExplicit: nextSong?.explicitStatus === ExplicitStatus.EXPLICIT,
bottomImage: nextImageUrl, bottomImage: nextImageUrl,
current: 0, current: 0,
topExplicit: currentSong?.explicitStatus === ExplicitStatus.EXPLICIT,
topImage: currentImageUrl, topImage: currentImageUrl,
}); });
@@ -133,8 +148,14 @@ export const FullScreenPlayerImage = () => {
const isTop = imageStateRef.current.current === 0; const isTop = imageStateRef.current.current === 0;
setImageState({ setImageState({
bottomExplicit:
(isTop ? currentSong?.explicitStatus : nextSong?.explicitStatus) ===
ExplicitStatus.EXPLICIT,
bottomImage: isTop ? currentImageUrl : nextImageUrl, bottomImage: isTop ? currentImageUrl : nextImageUrl,
current: isTop ? 1 : 0, current: isTop ? 1 : 0,
topExplicit:
(isTop ? nextSong?.explicitStatus : currentSong?.explicitStatus) ===
ExplicitStatus.EXPLICIT,
topImage: isTop ? nextImageUrl : currentImageUrl, topImage: isTop ? nextImageUrl : currentImageUrl,
}); });
@@ -146,6 +167,8 @@ export const FullScreenPlayerImage = () => {
nextSong?._uniqueId, nextSong?._uniqueId,
nextImageUrl, nextImageUrl,
setImageState, setImageState,
currentSong?.explicitStatus,
nextSong?.explicitStatus,
]); ]);
return ( return (
@@ -165,6 +188,7 @@ export const FullScreenPlayerImage = () => {
custom={{ isOpen: imageState.current === 0 }} custom={{ isOpen: imageState.current === 0 }}
draggable={false} draggable={false}
exit="closed" exit="closed"
explicit={blurExplicitImages && imageState.topExplicit}
initial="closed" initial="closed"
key={`top-${currentSong?._uniqueId || 'none'}`} key={`top-${currentSong?._uniqueId || 'none'}`}
placeholder="var(--theme-colors-foreground-muted)" placeholder="var(--theme-colors-foreground-muted)"
@@ -180,6 +204,7 @@ export const FullScreenPlayerImage = () => {
custom={{ isOpen: imageState.current === 1 }} custom={{ isOpen: imageState.current === 1 }}
draggable={false} draggable={false}
exit="closed" exit="closed"
explicit={blurExplicitImages && imageState.bottomExplicit}
initial="closed" initial="closed"
key={`bottom-${currentSong?._uniqueId || 'none'}`} key={`bottom-${currentSong?._uniqueId || 'none'}`}
placeholder="var(--theme-colors-foreground-muted)" placeholder="var(--theme-colors-foreground-muted)"
@@ -53,6 +53,10 @@
border-radius: var(--theme-radius-md); border-radius: var(--theme-radius-md);
} }
.censored.sidebar-image {
filter: blur(20px);
}
.accordion-root { .accordion-root {
height: 100%; height: 100%;
} }
@@ -24,6 +24,7 @@ import {
useAppStore, useAppStore,
useAppStoreActions, useAppStoreActions,
useFullScreenPlayerStore, useFullScreenPlayerStore,
useGeneralSettings,
usePlayerSong, usePlayerSong,
useSetFullScreenPlayerStore, useSetFullScreenPlayerStore,
} from '/@/renderer/store'; } from '/@/renderer/store';
@@ -42,7 +43,7 @@ import { ImageUnloader } from '/@/shared/components/image/image';
import { ScrollArea } from '/@/shared/components/scroll-area/scroll-area'; import { ScrollArea } from '/@/shared/components/scroll-area/scroll-area';
import { Text } from '/@/shared/components/text/text'; import { Text } from '/@/shared/components/text/text';
import { Tooltip } from '/@/shared/components/tooltip/tooltip'; import { Tooltip } from '/@/shared/components/tooltip/tooltip';
import { LibraryItem } from '/@/shared/types/domain-types'; import { ExplicitStatus, LibraryItem } from '/@/shared/types/domain-types';
import { Platform } from '/@/shared/types/types'; import { Platform } from '/@/shared/types/types';
export const Sidebar = () => { export const Sidebar = () => {
@@ -167,6 +168,7 @@ const SidebarImage = () => {
const currentSong = usePlayerSong(); const currentSong = usePlayerSong();
const isRadioActive = useIsRadioActive(); const isRadioActive = useIsRadioActive();
const { isPlaying: isRadioPlaying } = useRadioPlayer(); const { isPlaying: isRadioPlaying } = useRadioPlayer();
const { blurExplicitImages } = useGeneralSettings();
const imageUrl = useItemImageUrl({ const imageUrl = useItemImageUrl({
id: currentSong?.imageId || undefined, id: currentSong?.imageId || undefined,
@@ -235,7 +237,15 @@ const SidebarImage = () => {
<Icon color="muted" icon="radio" size="40%" /> <Icon color="muted" icon="radio" size="40%" />
</Center> </Center>
) : imageUrl ? ( ) : imageUrl ? (
<img className={styles.sidebarImage} loading="eager" src={imageUrl} /> <img
className={clsx(styles.sidebarImage, {
[styles.censored]:
currentSong?.explicitStatus === ExplicitStatus.EXPLICIT &&
blurExplicitImages,
})}
loading="eager"
src={imageUrl}
/>
) : ( ) : (
<ImageUnloader icon="emptySongImage" /> <ImageUnloader icon="emptySongImage" />
)} )}