mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge pull request #6447 from thornbill/refactor-playing-text
Refactor item text lines
This commit is contained in:
commit
18de10f2ea
6 changed files with 167 additions and 103 deletions
102
src/apps/stable/features/playback/utils/itemText.test.ts
Normal file
102
src/apps/stable/features/playback/utils/itemText.test.ts
Normal file
|
@ -0,0 +1,102 @@
|
|||
import { MediaType } from '@jellyfin/sdk/lib/generated-client/models/media-type';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type { ItemDto } from 'types/base/models/item-dto';
|
||||
|
||||
import { getItemTextLines } from './itemText';
|
||||
|
||||
describe('getItemTextLines', () => {
|
||||
it('Should return undefined if item is invalid', () => {
|
||||
let lines = getItemTextLines({});
|
||||
expect(lines).toBeUndefined();
|
||||
lines = getItemTextLines(null);
|
||||
expect(lines).toBeUndefined();
|
||||
lines = getItemTextLines(undefined);
|
||||
expect(lines).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Should return the name and index number', () => {
|
||||
const item: ItemDto = {
|
||||
Name: 'Item Name'
|
||||
};
|
||||
let lines = getItemTextLines(item);
|
||||
expect(lines).toBeDefined();
|
||||
expect(lines).toHaveLength(1);
|
||||
expect(lines?.[0]).toBe(item.Name);
|
||||
|
||||
item.MediaType = MediaType.Video;
|
||||
item.IndexNumber = 5;
|
||||
lines = getItemTextLines(item);
|
||||
expect(lines).toBeDefined();
|
||||
expect(lines).toHaveLength(1);
|
||||
expect(lines?.[0]).toBe(`${item.IndexNumber} - ${item.Name}`);
|
||||
|
||||
item.ParentIndexNumber = 2;
|
||||
lines = getItemTextLines(item);
|
||||
expect(lines).toBeDefined();
|
||||
expect(lines).toHaveLength(1);
|
||||
expect(lines?.[0]).toBe(`${item.ParentIndexNumber}.${item.IndexNumber} - ${item.Name}`);
|
||||
});
|
||||
|
||||
it('Should add artist names', () => {
|
||||
let item: ItemDto = {
|
||||
Name: 'Item Name',
|
||||
ArtistItems: [
|
||||
{ Name: 'Artist 1' },
|
||||
{ Name: 'Artist 2' }
|
||||
]
|
||||
};
|
||||
let lines = getItemTextLines(item);
|
||||
expect(lines).toBeDefined();
|
||||
expect(lines).toHaveLength(2);
|
||||
expect(lines?.[0]).toBe(item.Name);
|
||||
expect(lines?.[1]).toBe('Artist 1, Artist 2');
|
||||
|
||||
item = {
|
||||
Name: 'Item Name',
|
||||
Artists: [
|
||||
'Artist 1',
|
||||
'Artist 2'
|
||||
]
|
||||
};
|
||||
lines = getItemTextLines(item);
|
||||
expect(lines).toBeDefined();
|
||||
expect(lines).toHaveLength(2);
|
||||
expect(lines?.[0]).toBe(item.Name);
|
||||
expect(lines?.[1]).toBe('Artist 1, Artist 2');
|
||||
});
|
||||
|
||||
it('Should add album or series name', () => {
|
||||
let item: ItemDto = {
|
||||
Name: 'Item Name',
|
||||
SeriesName: 'Series'
|
||||
};
|
||||
let lines = getItemTextLines(item);
|
||||
expect(lines).toBeDefined();
|
||||
expect(lines).toHaveLength(2);
|
||||
expect(lines?.[0]).toBe(item.SeriesName);
|
||||
expect(lines?.[1]).toBe(item.Name);
|
||||
|
||||
item = {
|
||||
Name: 'Item Name',
|
||||
Album: 'Album'
|
||||
};
|
||||
lines = getItemTextLines(item);
|
||||
expect(lines).toBeDefined();
|
||||
expect(lines).toHaveLength(2);
|
||||
expect(lines?.[0]).toBe(item.Album);
|
||||
expect(lines?.[1]).toBe(item.Name);
|
||||
});
|
||||
|
||||
it('Should add production year', () => {
|
||||
const item = {
|
||||
Name: 'Item Name',
|
||||
ProductionYear: 2025
|
||||
};
|
||||
const lines = getItemTextLines(item);
|
||||
expect(lines).toBeDefined();
|
||||
expect(lines).toHaveLength(2);
|
||||
expect(lines?.[0]).toBe(item.Name);
|
||||
expect(lines?.[1]).toBe(String(item.ProductionYear));
|
||||
});
|
||||
});
|
44
src/apps/stable/features/playback/utils/itemText.ts
Normal file
44
src/apps/stable/features/playback/utils/itemText.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { MediaType } from '@jellyfin/sdk/lib/generated-client/models/media-type';
|
||||
|
||||
import type { ItemDto } from 'types/base/models/item-dto';
|
||||
|
||||
/**
|
||||
* Gets lines of text used to describe an item for display.
|
||||
* @param nowPlayingItem The item to describe
|
||||
* @param isYearIncluded Should the production year be included
|
||||
* @returns The list of strings describing the item for display
|
||||
*/
|
||||
export function getItemTextLines(
|
||||
nowPlayingItem: ItemDto | null | undefined,
|
||||
isYearIncluded = true
|
||||
) {
|
||||
let line1 = nowPlayingItem?.Name;
|
||||
if (nowPlayingItem?.MediaType === MediaType.Video) {
|
||||
if (nowPlayingItem.IndexNumber != null) {
|
||||
line1 = nowPlayingItem.IndexNumber + ' - ' + line1;
|
||||
}
|
||||
if (nowPlayingItem.ParentIndexNumber != null) {
|
||||
line1 = nowPlayingItem.ParentIndexNumber + '.' + line1;
|
||||
}
|
||||
}
|
||||
|
||||
let line2: string | null | undefined;
|
||||
if (nowPlayingItem?.ArtistItems?.length) {
|
||||
line2 = nowPlayingItem.ArtistItems.map(a => a.Name).join(', ');
|
||||
} else if (nowPlayingItem?.Artists?.length) {
|
||||
line2 = nowPlayingItem.Artists.join(', ');
|
||||
} else if (nowPlayingItem?.SeriesName || nowPlayingItem?.Album) {
|
||||
line2 = line1;
|
||||
line1 = nowPlayingItem.SeriesName || nowPlayingItem.Album;
|
||||
} else if (nowPlayingItem?.ProductionYear && isYearIncluded) {
|
||||
line2 = String(nowPlayingItem.ProductionYear);
|
||||
}
|
||||
|
||||
if (!line1) return;
|
||||
|
||||
const lines = [ line1 ];
|
||||
|
||||
if (line2) lines.push(line2);
|
||||
|
||||
return lines;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
import { MediaType } from '@jellyfin/sdk/lib/generated-client/models/media-type';
|
||||
|
||||
import { getImageUrl } from 'apps/stable/features/playback/utils/image';
|
||||
import { getItemTextLines } from 'apps/stable/features/playback/utils/itemText';
|
||||
import { PlaybackSubscriber } from 'apps/stable/features/playback/utils/playbackSubscriber';
|
||||
import { getNowPlayingNames } from 'components/playback/nowplayinghelper';
|
||||
import type { PlaybackManager } from 'components/playback/playbackmanager';
|
||||
import { MILLISECONDS_PER_SECOND, TICKS_PER_MILLISECOND } from 'constants/time';
|
||||
import browser from 'scripts/browser';
|
||||
|
@ -110,11 +110,11 @@ class MediaSessionSubscriber extends PlaybackSubscriber {
|
|||
}
|
||||
|
||||
const album = item.Album || undefined;
|
||||
const [ line1, line2 ] = getNowPlayingNames(item, false) || [];
|
||||
const [ line1, line2 ] = getItemTextLines(item, false) || [];
|
||||
// The artist will be the second line if present or the first line otherwise
|
||||
const artist = (line2 || line1)?.text;
|
||||
const artist = line2 || line1;
|
||||
// The title will be the first line if there are two lines
|
||||
const title = (line2 && line1)?.text;
|
||||
const title = line2 && line1;
|
||||
|
||||
if (hasNavigatorSession) {
|
||||
if (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue