mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-09 20:29:36 +02:00
add configuration to blur explicit album/song art
This commit is contained in:
@@ -936,6 +936,8 @@
|
|||||||
"showLyricsInSidebar": "show lyrics in player sidebar",
|
"showLyricsInSidebar": "show lyrics in player sidebar",
|
||||||
"showRatings_description": "controls if the star ratings feature shows up in the interface",
|
"showRatings_description": "controls if the star ratings feature shows up in the interface",
|
||||||
"showRatings": "show star ratings",
|
"showRatings": "show star ratings",
|
||||||
|
"blurExplicitImages": "blur explicit images",
|
||||||
|
"blurExplicitImages_description": "album and song artwork tagged as explicit will be blurred",
|
||||||
"enableGridMultiSelect": "enable grid multi-select",
|
"enableGridMultiSelect": "enable grid multi-select",
|
||||||
"enableGridMultiSelect_description": "when enabled, allows selecting multiple items in grid views. when disabled, clicking grid item images will navigate to the item page",
|
"enableGridMultiSelect_description": "when enabled, allows selecting multiple items in grid views. when disabled, clicking grid item images will navigate to the item page",
|
||||||
"showVisualizerInSidebar_description": "a panel will be added to the player sidebar that displays the visualizer",
|
"showVisualizerInSidebar_description": "a panel will be added to the player sidebar that displays the visualizer",
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ const CarouselItem = ({ album }: CarouselItemProps) => {
|
|||||||
containerClassName={styles.albumImageContainer}
|
containerClassName={styles.albumImageContainer}
|
||||||
enableDebounce={false}
|
enableDebounce={false}
|
||||||
enableViewport={false}
|
enableViewport={false}
|
||||||
|
explicitStatus={album.explicitStatus}
|
||||||
fetchPriority="high"
|
fetchPriority="high"
|
||||||
id={album.imageId}
|
id={album.imageId}
|
||||||
itemType={LibraryItem.ALBUM}
|
itemType={LibraryItem.ALBUM}
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ const CarouselItem = ({ album }: CarouselItemProps) => {
|
|||||||
containerClassName={styles.albumImageContainer}
|
containerClassName={styles.albumImageContainer}
|
||||||
enableDebounce={false}
|
enableDebounce={false}
|
||||||
enableViewport={false}
|
enableViewport={false}
|
||||||
|
explicitStatus={album.explicitStatus}
|
||||||
fetchPriority="high"
|
fetchPriority="high"
|
||||||
id={album.imageId}
|
id={album.imageId}
|
||||||
itemType={LibraryItem.ALBUM}
|
itemType={LibraryItem.ALBUM}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
z-index: 5;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|||||||
@@ -362,6 +362,9 @@ const CompactItemCard = ({
|
|||||||
[styles.isRound]: isRound,
|
[styles.isRound]: isRound,
|
||||||
})}
|
})}
|
||||||
enableDebounce={false}
|
enableDebounce={false}
|
||||||
|
explicitStatus={
|
||||||
|
'explicitStatus' in data && data ? data.explicitStatus : null
|
||||||
|
}
|
||||||
id={data?.imageId}
|
id={data?.imageId}
|
||||||
itemType={itemType}
|
itemType={itemType}
|
||||||
src={(data as Album | AlbumArtist | Playlist | Song)?.imageUrl}
|
src={(data as Album | AlbumArtist | Playlist | Song)?.imageUrl}
|
||||||
@@ -596,6 +599,9 @@ const DefaultItemCard = ({
|
|||||||
<ItemImage
|
<ItemImage
|
||||||
className={clsx(styles.image, { [styles.isRound]: isRound })}
|
className={clsx(styles.image, { [styles.isRound]: isRound })}
|
||||||
enableDebounce={false}
|
enableDebounce={false}
|
||||||
|
explicitStatus={
|
||||||
|
'explicitStatus' in data && data ? data.explicitStatus : null
|
||||||
|
}
|
||||||
id={data?.imageId}
|
id={data?.imageId}
|
||||||
itemType={itemType}
|
itemType={itemType}
|
||||||
src={(data as Album | AlbumArtist | Playlist | Song)?.imageUrl}
|
src={(data as Album | AlbumArtist | Playlist | Song)?.imageUrl}
|
||||||
@@ -893,6 +899,9 @@ const PosterItemCard = ({
|
|||||||
<ItemImage
|
<ItemImage
|
||||||
className={clsx(styles.image, { [styles.isRound]: isRound })}
|
className={clsx(styles.image, { [styles.isRound]: isRound })}
|
||||||
enableDebounce={false}
|
enableDebounce={false}
|
||||||
|
explicitStatus={
|
||||||
|
'explicitStatus' in data && data ? data.explicitStatus : null
|
||||||
|
}
|
||||||
id={(data as { imageId: string })?.imageId}
|
id={(data as { imageId: string })?.imageId}
|
||||||
itemType={itemType}
|
itemType={itemType}
|
||||||
src={(data as { imageUrl: string })?.imageUrl}
|
src={(data as { imageUrl: string })?.imageUrl}
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ import {
|
|||||||
getServerById,
|
getServerById,
|
||||||
useAuthStore,
|
useAuthStore,
|
||||||
useCurrentServerId,
|
useCurrentServerId,
|
||||||
|
useGeneralSettings,
|
||||||
useImageRes,
|
useImageRes,
|
||||||
useSettingsStore,
|
useSettingsStore,
|
||||||
} from '/@/renderer/store';
|
} from '/@/renderer/store';
|
||||||
import { BaseImage, ImageProps } from '/@/shared/components/image/image';
|
import { BaseImage, ImageProps } from '/@/shared/components/image/image';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { ExplicitStatus, LibraryItem } from '/@/shared/types/domain-types';
|
||||||
|
|
||||||
const getUnloaderIcon = (itemType: LibraryItem) => {
|
const getUnloaderIcon = (itemType: LibraryItem) => {
|
||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
@@ -34,6 +35,7 @@ const getUnloaderIcon = (itemType: LibraryItem) => {
|
|||||||
|
|
||||||
const BaseItemImage = (
|
const BaseItemImage = (
|
||||||
props: Omit<ImageProps, 'id' | 'src'> & {
|
props: Omit<ImageProps, 'id' | 'src'> & {
|
||||||
|
explicitStatus?: ExplicitStatus | null;
|
||||||
id?: null | string;
|
id?: null | string;
|
||||||
itemType: LibraryItem;
|
itemType: LibraryItem;
|
||||||
serverId?: null | string;
|
serverId?: null | string;
|
||||||
@@ -41,7 +43,8 @@ const BaseItemImage = (
|
|||||||
type?: keyof z.infer<typeof GeneralSettingsSchema>['imageRes'];
|
type?: keyof z.infer<typeof GeneralSettingsSchema>['imageRes'];
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
const { serverId, src, ...rest } = props;
|
const { explicitStatus, serverId, src, ...rest } = props;
|
||||||
|
const { blurExplicitImages } = useGeneralSettings();
|
||||||
|
|
||||||
const imageUrl = useItemImageUrl({
|
const imageUrl = useItemImageUrl({
|
||||||
id: props.id,
|
id: props.id,
|
||||||
@@ -51,8 +54,11 @@ const BaseItemImage = (
|
|||||||
type: props.type,
|
type: props.type,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isExplicit = blurExplicitImages && explicitStatus === ExplicitStatus.EXPLICIT;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseImage
|
<BaseImage
|
||||||
|
isExplicit={isExplicit}
|
||||||
src={imageUrl}
|
src={imageUrl}
|
||||||
unloaderIcon={getUnloaderIcon(props.itemType)}
|
unloaderIcon={getUnloaderIcon(props.itemType)}
|
||||||
{...rest}
|
{...rest}
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ const ImageColumnBase = (props: ItemTableListInnerColumn) => {
|
|||||||
})}
|
})}
|
||||||
enableDebounce={true}
|
enableDebounce={true}
|
||||||
enableViewport={false}
|
enableViewport={false}
|
||||||
|
explicitStatus={item?.explicitStatus}
|
||||||
id={item?.imageId}
|
id={item?.imageId}
|
||||||
itemType={item?._itemType}
|
itemType={item?._itemType}
|
||||||
src={item?.imageUrl}
|
src={item?.imageUrl}
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ export const DefaultTitleCombinedColumn = (props: ItemTableListInnerColumn) => {
|
|||||||
containerClassName={styles.image}
|
containerClassName={styles.image}
|
||||||
enableDebounce={true}
|
enableDebounce={true}
|
||||||
enableViewport={false}
|
enableViewport={false}
|
||||||
|
explicitStatus={item?.explicitStatus}
|
||||||
id={item?.imageId}
|
id={item?.imageId}
|
||||||
itemType={item?._itemType}
|
itemType={item?._itemType}
|
||||||
src={item?.imageUrl}
|
src={item?.imageUrl}
|
||||||
@@ -246,6 +247,7 @@ export const QueueSongTitleCombinedColumn = (props: ItemTableListInnerColumn) =>
|
|||||||
>
|
>
|
||||||
<ItemImage
|
<ItemImage
|
||||||
containerClassName={styles.image}
|
containerClassName={styles.image}
|
||||||
|
explicitStatus={item?.explicitStatus}
|
||||||
id={item?.imageId}
|
id={item?.imageId}
|
||||||
itemType={item?._itemType}
|
itemType={item?._itemType}
|
||||||
serverId={item?._serverId}
|
serverId={item?._serverId}
|
||||||
|
|||||||
@@ -220,6 +220,7 @@ export const AlbumDetailHeader = forwardRef<HTMLDivElement>((_props, ref) => {
|
|||||||
<LibraryHeader
|
<LibraryHeader
|
||||||
item={{
|
item={{
|
||||||
children: headerItem,
|
children: headerItem,
|
||||||
|
explicitStatus: detailQuery?.data?.explicitStatus ?? null,
|
||||||
imageId: detailQuery?.data?.imageId,
|
imageId: detailQuery?.data?.imageId,
|
||||||
imageUrl: detailQuery?.data?.imageUrl,
|
imageUrl: detailQuery?.data?.imageUrl,
|
||||||
route: AppRoute.LIBRARY_ALBUMS,
|
route: AppRoute.LIBRARY_ALBUMS,
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ const DummyAlbumDetailRoute = () => {
|
|||||||
<LibraryHeader
|
<LibraryHeader
|
||||||
imageUrl={imageUrl}
|
imageUrl={imageUrl}
|
||||||
item={{
|
item={{
|
||||||
|
explicitStatus: detailQuery?.data?.explicitStatus ?? null,
|
||||||
imageId: detailQuery?.data?.imageId,
|
imageId: detailQuery?.data?.imageId,
|
||||||
imageUrl: detailQuery?.data?.imageUrl,
|
imageUrl: detailQuery?.data?.imageUrl,
|
||||||
route: AppRoute.LIBRARY_SONGS,
|
route: AppRoute.LIBRARY_SONGS,
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ export const LeftControls = () => {
|
|||||||
)}
|
)}
|
||||||
enableDebounce={false}
|
enableDebounce={false}
|
||||||
enableViewport={false}
|
enableViewport={false}
|
||||||
|
explicitStatus={currentSong?.explicitStatus}
|
||||||
fetchPriority="high"
|
fetchPriority="high"
|
||||||
id={currentSong?.imageId}
|
id={currentSong?.imageId}
|
||||||
itemType={LibraryItem.SONG}
|
itemType={LibraryItem.SONG}
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ export const MobilePlayerbar = () => {
|
|||||||
)}
|
)}
|
||||||
enableDebounce={false}
|
enableDebounce={false}
|
||||||
enableViewport={false}
|
enableViewport={false}
|
||||||
|
explicitStatus={currentSong.explicitStatus}
|
||||||
fetchPriority="high"
|
fetchPriority="high"
|
||||||
id={currentSong.imageId}
|
id={currentSong.imageId}
|
||||||
itemType={LibraryItem.SONG}
|
itemType={LibraryItem.SONG}
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ export const CommandPalette = ({ modalProps }: CommandPaletteProps) => {
|
|||||||
>
|
>
|
||||||
{({ isHighlighted }) => (
|
{({ isHighlighted }) => (
|
||||||
<LibraryCommandItem
|
<LibraryCommandItem
|
||||||
|
explicitStatus={album.explicitStatus}
|
||||||
id={album.id}
|
id={album.id}
|
||||||
imageId={album.imageId}
|
imageId={album.imageId}
|
||||||
imageUrl={album.imageUrl}
|
imageUrl={album.imageUrl}
|
||||||
@@ -238,6 +239,7 @@ export const CommandPalette = ({ modalProps }: CommandPaletteProps) => {
|
|||||||
>
|
>
|
||||||
{({ isHighlighted }) => (
|
{({ isHighlighted }) => (
|
||||||
<LibraryCommandItem
|
<LibraryCommandItem
|
||||||
|
explicitStatus={song.explicitStatus}
|
||||||
id={song.id}
|
id={song.id}
|
||||||
imageId={song.imageId}
|
imageId={song.imageId}
|
||||||
imageUrl={song.imageUrl}
|
imageUrl={song.imageUrl}
|
||||||
|
|||||||
@@ -13,11 +13,12 @@ import { useCurrentServer } from '/@/renderer/store';
|
|||||||
import { ActionIcon, ActionIconGroup } from '/@/shared/components/action-icon/action-icon';
|
import { ActionIcon, ActionIconGroup } from '/@/shared/components/action-icon/action-icon';
|
||||||
import { Flex } from '/@/shared/components/flex/flex';
|
import { Flex } from '/@/shared/components/flex/flex';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { LibraryItem, Song } from '/@/shared/types/domain-types';
|
import { ExplicitStatus, LibraryItem, Song } from '/@/shared/types/domain-types';
|
||||||
import { Play } from '/@/shared/types/types';
|
import { Play } from '/@/shared/types/types';
|
||||||
|
|
||||||
interface LibraryCommandItemProps {
|
interface LibraryCommandItemProps {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
explicitStatus?: ExplicitStatus | null;
|
||||||
id: string;
|
id: string;
|
||||||
imageId: null | string;
|
imageId: null | string;
|
||||||
imageUrl: null | string;
|
imageUrl: null | string;
|
||||||
@@ -30,6 +31,7 @@ interface LibraryCommandItemProps {
|
|||||||
|
|
||||||
export const LibraryCommandItem = ({
|
export const LibraryCommandItem = ({
|
||||||
disabled,
|
disabled,
|
||||||
|
explicitStatus,
|
||||||
id,
|
id,
|
||||||
imageId,
|
imageId,
|
||||||
imageUrl,
|
imageUrl,
|
||||||
@@ -100,6 +102,7 @@ export const LibraryCommandItem = ({
|
|||||||
<ItemImage
|
<ItemImage
|
||||||
alt="cover"
|
alt="cover"
|
||||||
className={styles.image}
|
className={styles.image}
|
||||||
|
explicitStatus={explicitStatus ?? song?.explicitStatus ?? null}
|
||||||
height={40}
|
height={40}
|
||||||
id={imageId}
|
id={imageId}
|
||||||
itemType={itemType}
|
itemType={itemType}
|
||||||
|
|||||||
@@ -621,6 +621,28 @@ export const ApplicationSettings = memo(() => {
|
|||||||
isHidden: false,
|
isHidden: false,
|
||||||
title: t('setting.showRatings', { postProcess: 'sentenceCase' }),
|
title: t('setting.showRatings', { postProcess: 'sentenceCase' }),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
control: (
|
||||||
|
<Switch
|
||||||
|
aria-label={t('setting.blurExplicitImages', { postProcess: 'sentenceCase' })}
|
||||||
|
defaultChecked={settings.blurExplicitImages}
|
||||||
|
onChange={(e) =>
|
||||||
|
setSettings({
|
||||||
|
general: {
|
||||||
|
...settings,
|
||||||
|
blurExplicitImages: e.currentTarget.checked,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
description: t('setting.blurExplicitImages', {
|
||||||
|
context: 'description',
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
}),
|
||||||
|
isHidden: false,
|
||||||
|
title: t('setting.blurExplicitImages', { postProcess: 'sentenceCase' }),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
control: (
|
control: (
|
||||||
<Switch
|
<Switch
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { BaseImage } from '/@/shared/components/image/image';
|
|||||||
import { Rating } from '/@/shared/components/rating/rating';
|
import { Rating } from '/@/shared/components/rating/rating';
|
||||||
import { Spinner } from '/@/shared/components/spinner/spinner';
|
import { Spinner } from '/@/shared/components/spinner/spinner';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { ExplicitStatus, LibraryItem } from '/@/shared/types/domain-types';
|
||||||
import { Play } from '/@/shared/types/types';
|
import { Play } from '/@/shared/types/types';
|
||||||
|
|
||||||
interface LibraryHeaderProps {
|
interface LibraryHeaderProps {
|
||||||
@@ -37,6 +37,7 @@ interface LibraryHeaderProps {
|
|||||||
imageUrl?: null | string;
|
imageUrl?: null | string;
|
||||||
item: {
|
item: {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
|
explicitStatus?: ExplicitStatus | null;
|
||||||
imageId?: null | string;
|
imageId?: null | string;
|
||||||
imageUrl?: null | string;
|
imageUrl?: null | string;
|
||||||
route: string;
|
route: string;
|
||||||
@@ -108,6 +109,7 @@ export const LibraryHeader = forwardRef(
|
|||||||
enableDebounce={false}
|
enableDebounce={false}
|
||||||
enableViewport={false}
|
enableViewport={false}
|
||||||
fetchPriority="high"
|
fetchPriority="high"
|
||||||
|
isExplicit={item.explicitStatus === ExplicitStatus.EXPLICIT}
|
||||||
src={imageUrl}
|
src={imageUrl}
|
||||||
style={{
|
style={{
|
||||||
maxHeight: '100%',
|
maxHeight: '100%',
|
||||||
@@ -120,7 +122,7 @@ export const LibraryHeader = forwardRef(
|
|||||||
),
|
),
|
||||||
fullScreen: true,
|
fullScreen: true,
|
||||||
});
|
});
|
||||||
}, [item.imageId, item.type]);
|
}, [item.explicitStatus, item.imageId, item.type]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx(styles.libraryHeader, containerClassName)} ref={ref}>
|
<div className={clsx(styles.libraryHeader, containerClassName)} ref={ref}>
|
||||||
@@ -142,6 +144,7 @@ export const LibraryHeader = forwardRef(
|
|||||||
containerClassName={styles.image}
|
containerClassName={styles.image}
|
||||||
enableDebounce={false}
|
enableDebounce={false}
|
||||||
enableViewport={false}
|
enableViewport={false}
|
||||||
|
explicitStatus={item.explicitStatus ?? null}
|
||||||
fetchPriority="high"
|
fetchPriority="high"
|
||||||
id={item.imageId}
|
id={item.imageId}
|
||||||
itemType={item.type as LibraryItem}
|
itemType={item.type as LibraryItem}
|
||||||
|
|||||||
@@ -416,6 +416,7 @@ export const GeneralSettingsSchema = z.object({
|
|||||||
artistItems: z.array(SortableItemSchema(ArtistItemSchema)),
|
artistItems: z.array(SortableItemSchema(ArtistItemSchema)),
|
||||||
artistRadioCount: z.number(),
|
artistRadioCount: z.number(),
|
||||||
artistReleaseTypeItems: z.array(SortableItemSchema(ArtistReleaseTypeItemSchema)),
|
artistReleaseTypeItems: z.array(SortableItemSchema(ArtistReleaseTypeItemSchema)),
|
||||||
|
blurExplicitImages: z.boolean(),
|
||||||
buttonSize: z.number(),
|
buttonSize: z.number(),
|
||||||
collections: z.array(CollectionSchema),
|
collections: z.array(CollectionSchema),
|
||||||
combinedLyricsAndVisualizer: z.boolean(),
|
combinedLyricsAndVisualizer: z.boolean(),
|
||||||
@@ -988,6 +989,7 @@ const initialState: SettingsState = {
|
|||||||
artistItems,
|
artistItems,
|
||||||
artistRadioCount: 20,
|
artistRadioCount: 20,
|
||||||
artistReleaseTypeItems,
|
artistReleaseTypeItems,
|
||||||
|
blurExplicitImages: false,
|
||||||
buttonSize: 15,
|
buttonSize: 15,
|
||||||
collections: [],
|
collections: [],
|
||||||
combinedLyricsAndVisualizer: false,
|
combinedLyricsAndVisualizer: false,
|
||||||
|
|||||||
@@ -27,11 +27,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.image-container {
|
.image-container {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
aspect-ratio: 1 / 1;
|
aspect-ratio: 1 / 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.censored .image {
|
||||||
|
filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.censored::after {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--theme-colors-background);
|
||||||
|
background-color: alpha(var(--theme-colors-background), 0.5);
|
||||||
|
border-radius: var(--theme-radius-md);
|
||||||
|
}
|
||||||
|
|
||||||
.unloader {
|
.unloader {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export interface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 's
|
|||||||
imageContainerProps?: Omit<ImageContainerProps, 'children'>;
|
imageContainerProps?: Omit<ImageContainerProps, 'children'>;
|
||||||
includeLoader?: boolean;
|
includeLoader?: boolean;
|
||||||
includeUnloader?: boolean;
|
includeUnloader?: boolean;
|
||||||
|
isExplicit?: boolean;
|
||||||
src: string | undefined;
|
src: string | undefined;
|
||||||
thumbHash?: string;
|
thumbHash?: string;
|
||||||
unloaderIcon?: keyof typeof AppIcon;
|
unloaderIcon?: keyof typeof AppIcon;
|
||||||
@@ -34,6 +35,7 @@ export interface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 's
|
|||||||
interface ImageContainerProps extends HTMLAttributes<HTMLDivElement> {
|
interface ImageContainerProps extends HTMLAttributes<HTMLDivElement> {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
enableAnimation?: boolean;
|
enableAnimation?: boolean;
|
||||||
|
isExplicit?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImageLoaderProps {
|
interface ImageLoaderProps {
|
||||||
@@ -58,6 +60,7 @@ export function BaseImage({
|
|||||||
imageContainerProps,
|
imageContainerProps,
|
||||||
includeLoader = true,
|
includeLoader = true,
|
||||||
includeUnloader = true,
|
includeUnloader = true,
|
||||||
|
isExplicit = false,
|
||||||
src,
|
src,
|
||||||
unloaderIcon = 'emptyImage',
|
unloaderIcon = 'emptyImage',
|
||||||
...props
|
...props
|
||||||
@@ -72,6 +75,7 @@ export function BaseImage({
|
|||||||
imageContainerProps={imageContainerProps}
|
imageContainerProps={imageContainerProps}
|
||||||
includeLoader={includeLoader}
|
includeLoader={includeLoader}
|
||||||
includeUnloader={includeUnloader}
|
includeUnloader={includeUnloader}
|
||||||
|
isExplicit={isExplicit}
|
||||||
src={src}
|
src={src}
|
||||||
unloaderIcon={unloaderIcon}
|
unloaderIcon={unloaderIcon}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -88,6 +92,7 @@ export function BaseImage({
|
|||||||
imageContainerProps={imageContainerProps}
|
imageContainerProps={imageContainerProps}
|
||||||
includeLoader={includeLoader}
|
includeLoader={includeLoader}
|
||||||
includeUnloader={includeUnloader}
|
includeUnloader={includeUnloader}
|
||||||
|
isExplicit={isExplicit}
|
||||||
src={src}
|
src={src}
|
||||||
unloaderIcon={unloaderIcon}
|
unloaderIcon={unloaderIcon}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -101,6 +106,7 @@ export function BaseImage({
|
|||||||
<ImageContainer
|
<ImageContainer
|
||||||
className={clsx(containerClassName, containerPropsClassName)}
|
className={clsx(containerClassName, containerPropsClassName)}
|
||||||
enableAnimation={enableAnimation}
|
enableAnimation={enableAnimation}
|
||||||
|
isExplicit={isExplicit}
|
||||||
{...restContainerProps}
|
{...restContainerProps}
|
||||||
>
|
>
|
||||||
{src ? (
|
{src ? (
|
||||||
@@ -135,6 +141,7 @@ function ImageWithDebounce({
|
|||||||
imageContainerProps,
|
imageContainerProps,
|
||||||
includeLoader,
|
includeLoader,
|
||||||
includeUnloader,
|
includeUnloader,
|
||||||
|
isExplicit = false,
|
||||||
src,
|
src,
|
||||||
unloaderIcon,
|
unloaderIcon,
|
||||||
...props
|
...props
|
||||||
@@ -176,6 +183,7 @@ function ImageWithDebounce({
|
|||||||
<ImageContainer
|
<ImageContainer
|
||||||
className={clsx(containerClassName, containerPropsClassName)}
|
className={clsx(containerClassName, containerPropsClassName)}
|
||||||
enableAnimation={enableAnimation}
|
enableAnimation={enableAnimation}
|
||||||
|
isExplicit={isExplicit}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
{...restContainerProps}
|
{...restContainerProps}
|
||||||
>
|
>
|
||||||
@@ -209,6 +217,7 @@ function ImageWithDebounce({
|
|||||||
<ImageContainer
|
<ImageContainer
|
||||||
className={clsx(containerClassName, containerPropsClassName)}
|
className={clsx(containerClassName, containerPropsClassName)}
|
||||||
enableAnimation={enableAnimation}
|
enableAnimation={enableAnimation}
|
||||||
|
isExplicit={isExplicit}
|
||||||
{...restContainerProps}
|
{...restContainerProps}
|
||||||
>
|
>
|
||||||
{effectiveSrc ? (
|
{effectiveSrc ? (
|
||||||
@@ -244,6 +253,7 @@ function ImageWithViewport({
|
|||||||
imageContainerProps,
|
imageContainerProps,
|
||||||
includeLoader,
|
includeLoader,
|
||||||
includeUnloader,
|
includeUnloader,
|
||||||
|
isExplicit = false,
|
||||||
src,
|
src,
|
||||||
unloaderIcon,
|
unloaderIcon,
|
||||||
...props
|
...props
|
||||||
@@ -275,6 +285,7 @@ function ImageWithViewport({
|
|||||||
<ImageContainer
|
<ImageContainer
|
||||||
className={clsx(containerClassName, containerPropsClassName)}
|
className={clsx(containerClassName, containerPropsClassName)}
|
||||||
enableAnimation={enableAnimation}
|
enableAnimation={enableAnimation}
|
||||||
|
isExplicit={isExplicit}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
{...restContainerProps}
|
{...restContainerProps}
|
||||||
>
|
>
|
||||||
@@ -347,19 +358,17 @@ export const Image = memo(BaseImage);
|
|||||||
|
|
||||||
const ImageContainer = forwardRef(
|
const ImageContainer = forwardRef(
|
||||||
(
|
(
|
||||||
{ children, className, enableAnimation, ...props }: ImageContainerProps,
|
{ children, className, isExplicit, ...props }: ImageContainerProps,
|
||||||
ref: ForwardedRef<HTMLDivElement>,
|
ref: ForwardedRef<HTMLDivElement>,
|
||||||
) => {
|
) => {
|
||||||
if (!enableAnimation) {
|
|
||||||
return (
|
|
||||||
<div className={clsx(styles.imageContainer, className)} ref={ref} {...props}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx(styles.imageContainer, className)} ref={ref} {...props}>
|
<div
|
||||||
|
className={clsx(styles.imageContainer, className, {
|
||||||
|
[styles.censored]: isExplicit,
|
||||||
|
})}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user