mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Fix default icon handling and add tests
This commit is contained in:
parent
cd14a6bcff
commit
2abc648dcf
3 changed files with 119 additions and 25 deletions
|
@ -1,7 +1,7 @@
|
||||||
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
||||||
import React, { type FC } from 'react';
|
import React, { type FC } from 'react';
|
||||||
import Icon from '@mui/material/Icon';
|
import Icon from '@mui/material/Icon';
|
||||||
import imageHelper from 'utils/image';
|
import { getItemTypeIcon, getLibraryIcon } from 'utils/image';
|
||||||
import DefaultName from './DefaultName';
|
import DefaultName from './DefaultName';
|
||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
|
||||||
|
@ -14,38 +14,24 @@ const DefaultIconText: FC<DefaultIconTextProps> = ({
|
||||||
item,
|
item,
|
||||||
defaultCardImageIcon
|
defaultCardImageIcon
|
||||||
}) => {
|
}) => {
|
||||||
if (item.CollectionType) {
|
let icon;
|
||||||
return (
|
|
||||||
<Icon
|
if (item.Type === BaseItemKind.CollectionFolder || item.CollectionType) {
|
||||||
className='cardImageIcon'
|
icon = getLibraryIcon(item.CollectionType);
|
||||||
sx={{ color: 'inherit', fontSize: '5em' }}
|
|
||||||
aria-hidden='true'
|
|
||||||
>
|
|
||||||
{imageHelper.getLibraryIcon(item.CollectionType)}
|
|
||||||
</Icon>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.Type && !(item.Type === BaseItemKind.TvChannel || item.Type === BaseItemKind.Studio )) {
|
if (!icon) {
|
||||||
return (
|
icon = getItemTypeIcon(item.Type, defaultCardImageIcon);
|
||||||
<Icon
|
|
||||||
className='cardImageIcon'
|
|
||||||
sx={{ color: 'inherit', fontSize: '5em' }}
|
|
||||||
aria-hidden='true'
|
|
||||||
>
|
|
||||||
{imageHelper.getItemTypeIcon(item.Type)}
|
|
||||||
</Icon>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defaultCardImageIcon) {
|
if (icon) {
|
||||||
return (
|
return (
|
||||||
<Icon
|
<Icon
|
||||||
className='cardImageIcon'
|
className='cardImageIcon'
|
||||||
sx={{ color: 'inherit', fontSize: '5em' }}
|
sx={{ color: 'inherit', fontSize: '5em' }}
|
||||||
aria-hidden='true'
|
aria-hidden='true'
|
||||||
>
|
>
|
||||||
{defaultCardImageIcon}
|
{icon}
|
||||||
</Icon>
|
</Icon>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
106
src/utils/image.test.ts
Normal file
106
src/utils/image.test.ts
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
import { getItemTypeIcon, getLibraryIcon } from './image';
|
||||||
|
import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
||||||
|
|
||||||
|
const ITEM_ICON_MAP: Record<string, string | undefined> = {
|
||||||
|
AggregateFolder: undefined,
|
||||||
|
Audio: 'audiotrack',
|
||||||
|
AudioBook: undefined,
|
||||||
|
BasePluginFolder: undefined,
|
||||||
|
Book: 'book',
|
||||||
|
BoxSet: 'video_library',
|
||||||
|
Channel: undefined,
|
||||||
|
ChannelFolderItem: undefined,
|
||||||
|
CollectionFolder: undefined,
|
||||||
|
Episode: 'tv',
|
||||||
|
Folder: 'folder',
|
||||||
|
Genre: undefined,
|
||||||
|
LiveTvChannel: undefined,
|
||||||
|
LiveTvProgram: undefined,
|
||||||
|
ManualPlaylistsFolder: undefined,
|
||||||
|
Movie: 'movie',
|
||||||
|
MusicAlbum: 'album',
|
||||||
|
MusicArtist: 'person',
|
||||||
|
MusicGenre: undefined,
|
||||||
|
MusicVideo: undefined,
|
||||||
|
Person: 'person',
|
||||||
|
Photo: 'photo',
|
||||||
|
PhotoAlbum: 'photo_album',
|
||||||
|
Playlist: 'queue',
|
||||||
|
PlaylistsFolder: undefined,
|
||||||
|
Program: 'live_tv',
|
||||||
|
Recording: undefined,
|
||||||
|
Season: undefined,
|
||||||
|
Series: 'tv',
|
||||||
|
Studio: undefined,
|
||||||
|
Trailer: undefined,
|
||||||
|
TvChannel: undefined,
|
||||||
|
TvProgram: undefined,
|
||||||
|
UserRootFolder: undefined,
|
||||||
|
UserView: undefined,
|
||||||
|
Video: undefined,
|
||||||
|
Year: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
const LIBRARY_ICON_MAP: Record<string, string | undefined> = {
|
||||||
|
Books: 'book',
|
||||||
|
Boxsets: 'video_library',
|
||||||
|
Folders: 'folder',
|
||||||
|
Homevideos: 'photo',
|
||||||
|
Livetv: 'live_tv',
|
||||||
|
Movies: 'movie',
|
||||||
|
Music: 'music_note',
|
||||||
|
Musicvideos: 'music_video',
|
||||||
|
Photos: 'photo',
|
||||||
|
Playlists: 'queue',
|
||||||
|
Trailers: 'theaters',
|
||||||
|
Tvshows: 'tv',
|
||||||
|
Unknown: 'folder'
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('getItemTypeIcon()', () => {
|
||||||
|
it('Should return the correct icon for item type', () => {
|
||||||
|
Object.entries(BaseItemKind).forEach(([key, value]) => {
|
||||||
|
expect(Object.prototype.hasOwnProperty.call(ITEM_ICON_MAP, key)).toBe(true);
|
||||||
|
expect(`${key}=${getItemTypeIcon(value)}`).toBe(`${key}=${ITEM_ICON_MAP[key]}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return undefined for undefined type', () => {
|
||||||
|
expect(getItemTypeIcon(undefined, 'default'))
|
||||||
|
.toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return the default icon for unknown type if provided', () => {
|
||||||
|
expect(getItemTypeIcon('foobar', 'default'))
|
||||||
|
.toBe('default');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return undefined for unknown type', () => {
|
||||||
|
expect(getItemTypeIcon('foobar'))
|
||||||
|
.toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getLibraryIcon()', () => {
|
||||||
|
it('Should return the correct icon for collection type', () => {
|
||||||
|
Object.entries(CollectionType).forEach(([key, value]) => {
|
||||||
|
expect(Object.prototype.hasOwnProperty.call(LIBRARY_ICON_MAP, key)).toBe(true);
|
||||||
|
expect(`${key}=${getLibraryIcon(value)}`).toBe(`${key}=${LIBRARY_ICON_MAP[key]}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return the correct icon for nonstandard types', () => {
|
||||||
|
expect(getLibraryIcon(undefined))
|
||||||
|
.toBe('quiz');
|
||||||
|
expect(getLibraryIcon('channels'))
|
||||||
|
.toBe('videocam');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return the default icon for unknown types', () => {
|
||||||
|
expect(getLibraryIcon('foobar'))
|
||||||
|
.toBe('folder');
|
||||||
|
});
|
||||||
|
});
|
|
@ -108,7 +108,7 @@ export function getLibraryIcon(library: CollectionType | string | null | undefin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getItemTypeIcon(itemType: BaseItemKind | string, defaultIcon?: string) {
|
export function getItemTypeIcon(itemType: BaseItemKind | string | undefined, defaultIcon?: string) {
|
||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
case BaseItemKind.MusicAlbum:
|
case BaseItemKind.MusicAlbum:
|
||||||
return 'album';
|
return 'album';
|
||||||
|
@ -136,8 +136,10 @@ export function getItemTypeIcon(itemType: BaseItemKind | string, defaultIcon?: s
|
||||||
return 'photo';
|
return 'photo';
|
||||||
case BaseItemKind.PhotoAlbum:
|
case BaseItemKind.PhotoAlbum:
|
||||||
return 'photo_album';
|
return 'photo_album';
|
||||||
|
case undefined:
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
return defaultIcon || 'folder';
|
return defaultIcon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue