Merge pull request #7491 from PeachesMLG/fix_jellyfin_sdk_type_errors
This commit is contained in:
Generated
+4
-4
@@ -18,7 +18,7 @@
|
|||||||
"@fontsource/noto-sans-sc": "5.2.6",
|
"@fontsource/noto-sans-sc": "5.2.6",
|
||||||
"@fontsource/noto-sans-tc": "5.2.6",
|
"@fontsource/noto-sans-tc": "5.2.6",
|
||||||
"@jellyfin/libass-wasm": "4.2.3",
|
"@jellyfin/libass-wasm": "4.2.3",
|
||||||
"@jellyfin/sdk": "0.0.0-unstable.202512091852",
|
"@jellyfin/sdk": "0.0.0-unstable.202601090504",
|
||||||
"@jellyfin/ux-web": "1.0.0",
|
"@jellyfin/ux-web": "1.0.0",
|
||||||
"@mui/icons-material": "6.4.12",
|
"@mui/icons-material": "6.4.12",
|
||||||
"@mui/material": "6.4.12",
|
"@mui/material": "6.4.12",
|
||||||
@@ -4130,9 +4130,9 @@
|
|||||||
"license": "LGPL-2.1-or-later AND (FTL OR GPL-2.0-or-later) AND MIT AND MIT-Modern-Variant AND ISC AND NTP AND Zlib AND BSL-1.0"
|
"license": "LGPL-2.1-or-later AND (FTL OR GPL-2.0-or-later) AND MIT AND MIT-Modern-Variant AND ISC AND NTP AND Zlib AND BSL-1.0"
|
||||||
},
|
},
|
||||||
"node_modules/@jellyfin/sdk": {
|
"node_modules/@jellyfin/sdk": {
|
||||||
"version": "0.0.0-unstable.202512091852",
|
"version": "0.0.0-unstable.202601090504",
|
||||||
"resolved": "https://registry.npmjs.org/@jellyfin/sdk/-/sdk-0.0.0-unstable.202512091852.tgz",
|
"resolved": "https://registry.npmjs.org/@jellyfin/sdk/-/sdk-0.0.0-unstable.202601090504.tgz",
|
||||||
"integrity": "sha512-N+QEsrKk4KculkV6KMBb7XpzTLWcXEzqTHbS+b4rov0VYVwR6DIsJkmUzB3hM2YZsrLIHEFKhFRy/r4itkFeHw==",
|
"integrity": "sha512-ZTtSUMYjyfin54dXGZ5i9fZxLkKbMPxxsFxnmLoSVrjNrvL8JMV3Thb0fevCgd5gpkJpLVJXpx5YjwNbrze6DQ==",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"axios": "^1.12.0"
|
"axios": "^1.12.0"
|
||||||
|
|||||||
+1
-1
@@ -85,7 +85,7 @@
|
|||||||
"@fontsource/noto-sans-sc": "5.2.6",
|
"@fontsource/noto-sans-sc": "5.2.6",
|
||||||
"@fontsource/noto-sans-tc": "5.2.6",
|
"@fontsource/noto-sans-tc": "5.2.6",
|
||||||
"@jellyfin/libass-wasm": "4.2.3",
|
"@jellyfin/libass-wasm": "4.2.3",
|
||||||
"@jellyfin/sdk": "0.0.0-unstable.202512091852",
|
"@jellyfin/sdk": "0.0.0-unstable.202601090504",
|
||||||
"@jellyfin/ux-web": "1.0.0",
|
"@jellyfin/ux-web": "1.0.0",
|
||||||
"@mui/icons-material": "6.4.12",
|
"@mui/icons-material": "6.4.12",
|
||||||
"@mui/material": "6.4.12",
|
"@mui/material": "6.4.12",
|
||||||
|
|||||||
@@ -1,35 +1,36 @@
|
|||||||
|
import type { FolderStorageDto } from '@jellyfin/sdk/lib/generated-client/models/folder-storage-dto';
|
||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
import { calculateUsedPercentage, calculateTotal } from './space';
|
import { calculateUsedPercentage, calculateTotal } from './space';
|
||||||
|
|
||||||
describe('calculateTotal()', () => {
|
describe('calculateTotal()', () => {
|
||||||
it('should return the total', () => {
|
it('should return the total', () => {
|
||||||
expect(calculateTotal({ FreeSpace: 1, UsedSpace: 2 })).toBe(3);
|
expect(calculateTotal({ FreeSpace: 1, UsedSpace: 2 } as FolderStorageDto)).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return -1 for invalid used space values', () => {
|
it('should return -1 for invalid used space values', () => {
|
||||||
expect(calculateTotal({ FreeSpace: 1 })).toBe(-1);
|
expect(calculateTotal({ FreeSpace: 1 } as FolderStorageDto)).toBe(-1);
|
||||||
expect(calculateTotal({ FreeSpace: 1, UsedSpace: -1 })).toBe(-1);
|
expect(calculateTotal({ FreeSpace: 1, UsedSpace: -1 } as FolderStorageDto)).toBe(-1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should treat invalid free space values as 0', () => {
|
it('should treat invalid free space values as 0', () => {
|
||||||
expect(calculateTotal({ UsedSpace: 1 })).toBe(1);
|
expect(calculateTotal({ UsedSpace: 1 } as FolderStorageDto)).toBe(1);
|
||||||
expect(calculateTotal({ FreeSpace: -1, UsedSpace: 1 })).toBe(1);
|
expect(calculateTotal({ FreeSpace: -1, UsedSpace: 1 } as FolderStorageDto)).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('calculateUsedPercentage', () => {
|
describe('calculateUsedPercentage', () => {
|
||||||
it('should return the percentage used', () => {
|
it('should return the percentage used', () => {
|
||||||
expect(calculateUsedPercentage({ FreeSpace: 1, UsedSpace: 3 })).toBe(75);
|
expect(calculateUsedPercentage({ FreeSpace: 1, UsedSpace: 3 } as FolderStorageDto)).toBe(75);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 0 for invalid used space values', () => {
|
it('should return 0 for invalid used space values', () => {
|
||||||
expect(calculateUsedPercentage({ FreeSpace: 1 })).toBe(0);
|
expect(calculateUsedPercentage({ FreeSpace: 1 } as FolderStorageDto)).toBe(0);
|
||||||
expect(calculateUsedPercentage({ FreeSpace: 1, UsedSpace: -1 })).toBe(0);
|
expect(calculateUsedPercentage({ FreeSpace: 1, UsedSpace: -1 } as FolderStorageDto)).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 100 for invalid free space values', () => {
|
it('should return 100 for invalid free space values', () => {
|
||||||
expect(calculateUsedPercentage({ UsedSpace: 1 })).toBe(100);
|
expect(calculateUsedPercentage({ UsedSpace: 1 } as FolderStorageDto)).toBe(100);
|
||||||
expect(calculateUsedPercentage({ FreeSpace: -1, UsedSpace: 1 })).toBe(100);
|
expect(calculateUsedPercentage({ FreeSpace: -1, UsedSpace: 1 } as FolderStorageDto)).toBe(100);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import type { NullableString } from 'types/base/common/shared/types';
|
|||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
|
||||||
interface PlayAllFromHereOptions {
|
interface PlayAllFromHereOptions {
|
||||||
item: ItemDto;
|
item?: ItemDto;
|
||||||
items: ItemDto[];
|
items: ItemDto[];
|
||||||
serverId: NullableString;
|
serverId: NullableString;
|
||||||
queue?: boolean;
|
queue?: boolean;
|
||||||
@@ -166,7 +166,7 @@ const MoreCommandsButton: FC<MoreCommandsButtonProps> = ({
|
|||||||
serverId: item?.ServerId
|
serverId: item?.ServerId
|
||||||
});
|
});
|
||||||
playAllFromHere({
|
playAllFromHere({
|
||||||
item: item || {},
|
item: item,
|
||||||
items: items || [],
|
items: items || [],
|
||||||
serverId: item?.ServerId
|
serverId: item?.ServerId
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
@@ -174,7 +174,7 @@ const MoreCommandsButton: FC<MoreCommandsButtonProps> = ({
|
|||||||
});
|
});
|
||||||
} else if (result.command === 'queueallfromhere') {
|
} else if (result.command === 'queueallfromhere') {
|
||||||
playAllFromHere({
|
playAllFromHere({
|
||||||
item: item || {},
|
item: item,
|
||||||
items: items || [],
|
items: items || [],
|
||||||
serverId: item?.ServerId,
|
serverId: item?.ServerId,
|
||||||
queue: true
|
queue: true
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export function getImageUrl(item: ItemDto, options: ImageOptions = {}) {
|
|||||||
const itemId = item.PrimaryImageItemId || item.Id;
|
const itemId = item.PrimaryImageItemId || item.Id;
|
||||||
|
|
||||||
if (itemId && item.ImageTags?.[options.type]) {
|
if (itemId && item.ImageTags?.[options.type]) {
|
||||||
options.tag = item.ImageTags[options.type];
|
options.tag = item.ImageTags[options.type] ?? undefined;
|
||||||
return ServerConnections.getApiClient(item.ServerId).getScaledImageUrl(itemId, options);
|
return ServerConnections.getApiClient(item.ServerId).getScaledImageUrl(itemId, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { getItemTextLines } from './itemText';
|
|||||||
|
|
||||||
describe('getItemTextLines', () => {
|
describe('getItemTextLines', () => {
|
||||||
it('Should return undefined if item is invalid', () => {
|
it('Should return undefined if item is invalid', () => {
|
||||||
let lines = getItemTextLines({});
|
let lines = getItemTextLines({} as ItemDto);
|
||||||
expect(lines).toBeUndefined();
|
expect(lines).toBeUndefined();
|
||||||
lines = getItemTextLines(null);
|
lines = getItemTextLines(null);
|
||||||
expect(lines).toBeUndefined();
|
expect(lines).toBeUndefined();
|
||||||
@@ -16,9 +16,9 @@ describe('getItemTextLines', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should return the name and index number', () => {
|
it('Should return the name and index number', () => {
|
||||||
const item: ItemDto = {
|
const item = {
|
||||||
Name: 'Item Name'
|
Name: 'Item Name'
|
||||||
};
|
} as ItemDto;
|
||||||
let lines = getItemTextLines(item);
|
let lines = getItemTextLines(item);
|
||||||
expect(lines).toBeDefined();
|
expect(lines).toBeDefined();
|
||||||
expect(lines).toHaveLength(1);
|
expect(lines).toHaveLength(1);
|
||||||
@@ -39,13 +39,13 @@ describe('getItemTextLines', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should add artist names', () => {
|
it('Should add artist names', () => {
|
||||||
let item: ItemDto = {
|
let item = {
|
||||||
Name: 'Item Name',
|
Name: 'Item Name',
|
||||||
ArtistItems: [
|
ArtistItems: [
|
||||||
{ Name: 'Artist 1' },
|
{ Name: 'Artist 1' },
|
||||||
{ Name: 'Artist 2' }
|
{ Name: 'Artist 2' }
|
||||||
]
|
]
|
||||||
};
|
} as ItemDto;
|
||||||
let lines = getItemTextLines(item);
|
let lines = getItemTextLines(item);
|
||||||
expect(lines).toBeDefined();
|
expect(lines).toBeDefined();
|
||||||
expect(lines).toHaveLength(2);
|
expect(lines).toHaveLength(2);
|
||||||
@@ -58,7 +58,7 @@ describe('getItemTextLines', () => {
|
|||||||
'Artist 1',
|
'Artist 1',
|
||||||
'Artist 2'
|
'Artist 2'
|
||||||
]
|
]
|
||||||
};
|
} as ItemDto;
|
||||||
lines = getItemTextLines(item);
|
lines = getItemTextLines(item);
|
||||||
expect(lines).toBeDefined();
|
expect(lines).toBeDefined();
|
||||||
expect(lines).toHaveLength(2);
|
expect(lines).toHaveLength(2);
|
||||||
@@ -67,10 +67,10 @@ describe('getItemTextLines', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should add album or series name', () => {
|
it('Should add album or series name', () => {
|
||||||
let item: ItemDto = {
|
let item = {
|
||||||
Name: 'Item Name',
|
Name: 'Item Name',
|
||||||
SeriesName: 'Series'
|
SeriesName: 'Series'
|
||||||
};
|
} as ItemDto;
|
||||||
let lines = getItemTextLines(item);
|
let lines = getItemTextLines(item);
|
||||||
expect(lines).toBeDefined();
|
expect(lines).toBeDefined();
|
||||||
expect(lines).toHaveLength(2);
|
expect(lines).toHaveLength(2);
|
||||||
@@ -80,7 +80,7 @@ describe('getItemTextLines', () => {
|
|||||||
item = {
|
item = {
|
||||||
Name: 'Item Name',
|
Name: 'Item Name',
|
||||||
Album: 'Album'
|
Album: 'Album'
|
||||||
};
|
} as ItemDto;
|
||||||
lines = getItemTextLines(item);
|
lines = getItemTextLines(item);
|
||||||
expect(lines).toBeDefined();
|
expect(lines).toBeDefined();
|
||||||
expect(lines).toHaveLength(2);
|
expect(lines).toHaveLength(2);
|
||||||
@@ -92,7 +92,7 @@ describe('getItemTextLines', () => {
|
|||||||
const item = {
|
const item = {
|
||||||
Name: 'Item Name',
|
Name: 'Item Name',
|
||||||
ProductionYear: 2025
|
ProductionYear: 2025
|
||||||
};
|
} as ItemDto;
|
||||||
const lines = getItemTextLines(item);
|
const lines = getItemTextLines(item);
|
||||||
expect(lines).toBeDefined();
|
expect(lines).toBeDefined();
|
||||||
expect(lines).toHaveLength(2);
|
expect(lines).toHaveLength(2);
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import type { CardOptions } from 'types/cardOptions';
|
|||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
|
||||||
interface CardProps {
|
interface CardProps {
|
||||||
item?: ItemDto;
|
item: ItemDto;
|
||||||
cardOptions: CardOptions;
|
cardOptions: CardOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Card: FC<CardProps> = ({ item = {}, cardOptions }) => {
|
const Card: FC<CardProps> = ({ item, cardOptions }) => {
|
||||||
const { getCardWrapperProps, getCardBoxProps } = useCard({ item, cardOptions } );
|
const { getCardWrapperProps, getCardBoxProps } = useCard({ item, cardOptions } );
|
||||||
const cardWrapperProps = getCardWrapperProps();
|
const cardWrapperProps = getCardWrapperProps();
|
||||||
const cardBoxProps = getCardBoxProps();
|
const cardBoxProps = getCardBoxProps();
|
||||||
|
|||||||
@@ -217,6 +217,7 @@ function getParentTitle(
|
|||||||
.map(artist => {
|
.map(artist => {
|
||||||
const artistItem: ItemDto = {
|
const artistItem: ItemDto = {
|
||||||
...artist,
|
...artist,
|
||||||
|
Key: artist.Id ?? '',
|
||||||
Type: BaseItemKind.MusicArtist,
|
Type: BaseItemKind.MusicArtist,
|
||||||
IsFolder: true
|
IsFolder: true
|
||||||
};
|
};
|
||||||
@@ -511,6 +512,7 @@ function getChannelName(item: ItemDto) {
|
|||||||
if (item.ChannelId) {
|
if (item.ChannelId) {
|
||||||
return getTextActionButton(
|
return getTextActionButton(
|
||||||
{
|
{
|
||||||
|
Key: item.ChannelId,
|
||||||
Id: item.ChannelId,
|
Id: item.ChannelId,
|
||||||
ServerId: item.ServerId,
|
ServerId: item.ServerId,
|
||||||
Name: item.ChannelName,
|
Name: item.ChannelName,
|
||||||
@@ -598,6 +600,7 @@ function getMediaTitle(cardOptions: CardOptions, item: ItemDto): TextLine {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return getTextActionButton({
|
return getTextActionButton({
|
||||||
|
Key: item.Id ?? '',
|
||||||
Id: item.Id,
|
Id: item.Id,
|
||||||
ServerId: item.ServerId,
|
ServerId: item.ServerId,
|
||||||
Name: name,
|
Name: name,
|
||||||
@@ -620,6 +623,7 @@ function getParentTitleOrTitle(
|
|||||||
) {
|
) {
|
||||||
if (item.SeriesId) {
|
if (item.SeriesId) {
|
||||||
return getTextActionButton({
|
return getTextActionButton({
|
||||||
|
Key: item.SeriesId,
|
||||||
Id: item.SeriesId,
|
Id: item.SeriesId,
|
||||||
ServerId: item.ServerId,
|
ServerId: item.ServerId,
|
||||||
Name: item.SeriesName,
|
Name: item.SeriesName,
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ function useCard({ item, cardOptions }: UseCardProps) {
|
|||||||
shape
|
shape
|
||||||
});
|
});
|
||||||
const imgUrl = imgInfo.imgUrl;
|
const imgUrl = imgInfo.imgUrl;
|
||||||
const blurhash = imgInfo.blurhash;
|
const blurhash = imgInfo.blurhash ?? undefined;
|
||||||
const forceName = imgInfo.forceName;
|
const forceName = imgInfo.forceName;
|
||||||
const coveredImage = cardOptions.coverImage ?? imgInfo.coverImage;
|
const coveredImage = cardOptions.coverImage ?? imgInfo.coverImage;
|
||||||
const overlayText = cardOptions.overlayText;
|
const overlayText = cardOptions.overlayText;
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ function shouldShowPreferBanner(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function shouldShowPreferDisc(
|
function shouldShowPreferDisc(
|
||||||
imageTagsDisc: string | undefined,
|
imageTagsDisc: string | null | undefined,
|
||||||
cardOptions: CardOptions
|
cardOptions: CardOptions
|
||||||
): boolean {
|
): boolean {
|
||||||
return cardOptions.preferDisc === true && Boolean(imageTagsDisc);
|
return cardOptions.preferDisc === true && Boolean(imageTagsDisc);
|
||||||
|
|||||||
@@ -154,8 +154,8 @@ const useIndicator = (item: ItemDto) => {
|
|||||||
|
|
||||||
const getPlayedIndicator = () => {
|
const getPlayedIndicator = () => {
|
||||||
if (enablePlayedIndicator(item)) {
|
if (enablePlayedIndicator(item)) {
|
||||||
const userData = item.UserData || {};
|
const userData = item.UserData;
|
||||||
if (userData.UnplayedItemCount) {
|
if (userData?.UnplayedItemCount) {
|
||||||
return (
|
return (
|
||||||
<Box className='countIndicator indicator unplayedItemCount'>
|
<Box className='countIndicator indicator unplayedItemCount'>
|
||||||
{formatCountIndicator(userData.UnplayedItemCount)}
|
{formatCountIndicator(userData.UnplayedItemCount)}
|
||||||
@@ -164,9 +164,9 @@ const useIndicator = (item: ItemDto) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(userData.PlayedPercentage
|
(userData?.PlayedPercentage
|
||||||
&& userData.PlayedPercentage >= 100)
|
&& userData?.PlayedPercentage >= 100)
|
||||||
|| userData.Played
|
|| userData?.Played
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<Box className='playedIndicator indicator'>
|
<Box className='playedIndicator indicator'>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ interface ListImageContainerProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ListImageContainer: FC<ListImageContainerProps> = ({
|
const ListImageContainer: FC<ListImageContainerProps> = ({
|
||||||
item = {},
|
item,
|
||||||
listOptions,
|
listOptions,
|
||||||
action,
|
action,
|
||||||
isLargeStyle,
|
isLargeStyle,
|
||||||
@@ -73,7 +73,7 @@ const ListImageContainer: FC<ListImageContainerProps> = ({
|
|||||||
className={imageClass}
|
className={imageClass}
|
||||||
>
|
>
|
||||||
|
|
||||||
<Media item={item} imgUrl={imgUrl} blurhash={blurhash} defaultCardImageIcon={defaultCardImageIcon} />
|
<Media item={item} imgUrl={imgUrl} blurhash={blurhash ?? undefined} defaultCardImageIcon={defaultCardImageIcon} />
|
||||||
|
|
||||||
{disableIndicators !== true && mediaSourceIndicator}
|
{disableIndicators !== true && mediaSourceIndicator}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ interface ListItemBodyProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ListItemBody: FC<ListItemBodyProps> = ({
|
const ListItemBody: FC<ListItemBodyProps> = ({
|
||||||
item = {},
|
item,
|
||||||
listOptions = {},
|
listOptions = {},
|
||||||
action,
|
action,
|
||||||
isLargeStyle,
|
isLargeStyle,
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ function createPlaylist(dlg: DialogElement) {
|
|||||||
return getPlaylistsApi(api)
|
return getPlaylistsApi(api)
|
||||||
.createPlaylist({
|
.createPlaylist({
|
||||||
createPlaylistDto: {
|
createPlaylistDto: {
|
||||||
Name: name,
|
Name: name ?? '',
|
||||||
IsPublic: dlg.querySelector<HTMLInputElement>('#chkPlaylistPublic')?.checked,
|
IsPublic: dlg.querySelector<HTMLInputElement>('#chkPlaylistPublic')?.checked,
|
||||||
Ids: itemIds?.split(','),
|
Ids: itemIds?.split(','),
|
||||||
UserId: apiClient.getCurrentUserId()
|
UserId: apiClient.getCurrentUserId()
|
||||||
|
|||||||
Reference in New Issue
Block a user