1
0
Fork 0
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:
Bill Thornton 2025-02-13 16:23:07 -05:00 committed by GitHub
commit 18de10f2ea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 167 additions and 103 deletions

View 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));
});
});

View 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;
}

View file

@ -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 (