diff --git a/src/controllers/lyrics.types.ts b/src/apps/stable/features/lyrics/constants/autoScroll.ts similarity index 100% rename from src/controllers/lyrics.types.ts rename to src/apps/stable/features/lyrics/constants/autoScroll.ts diff --git a/src/controllers/lyrics.html b/src/controllers/lyrics.html index d1e7b662c..79b923678 100644 --- a/src/controllers/lyrics.html +++ b/src/controllers/lyrics.html @@ -1,6 +1,6 @@
-
+
diff --git a/src/controllers/lyrics.js b/src/controllers/lyrics.js index 36ae408bc..74f674140 100644 --- a/src/controllers/lyrics.js +++ b/src/controllers/lyrics.js @@ -1,20 +1,21 @@ +import { getLyricsApi } from '@jellyfin/sdk/lib/utils/api/lyrics-api'; import escapeHtml from 'escape-html'; +import { AutoScroll } from 'apps/stable/features/lyrics/constants/autoScroll'; import autoFocuser from 'components/autoFocuser'; -import { appRouter } from '../components/router/appRouter'; +import { appRouter } from 'components/router/appRouter'; import layoutManager from 'components/layoutManager'; -import { playbackManager } from '../components/playback/playbackmanager'; +import { playbackManager } from 'components/playback/playbackmanager'; import scrollManager from 'components/scrollManager'; import focusManager from 'components/focusManager'; - -import keyboardNavigation from 'scripts/keyboardNavigation'; import globalize from 'lib/globalize'; import { ServerConnections } from 'lib/jellyfin-apiclient'; +import keyboardNavigation from 'scripts/keyboardNavigation'; import LibraryMenu from 'scripts/libraryMenu'; import Events from 'utils/events'; +import { toApi } from 'utils/jellyfin-apiclient/compat'; import '../styles/lyrics.scss'; -import { AutoScroll } from './lyrics.types'; let currentPlayer; let currentItem; @@ -23,21 +24,17 @@ let savedLyrics; let isDynamicLyric = false; let autoScroll = AutoScroll.Instant; -function dynamicLyricHtmlReducer(htmlAccumulator, lyric, index) { - if (layoutManager.tv) { - htmlAccumulator += ``; - } else { - htmlAccumulator += `
${escapeHtml(lyric.Text)}
`; - } - return htmlAccumulator; -} +function lyricHtmlReducer(htmlAccumulator, lyric, index) { + const elem = layoutManager.tv ? 'button' : 'div'; + const classes = []; + if (isDynamicLyric) classes.push('dynamicLyric'); + if (layoutManager.tv) classes.push('listItem', 'show-focus'); + const lyricTime = typeof lyric.Start !== 'undefined' ? `data-lyrictime="${lyric.Start}"` : ''; + + htmlAccumulator += `<${elem} class="lyricsLine ${classes.join(' ')}" id="lyricPosition${index}" ${lyricTime}> + ${escapeHtml(lyric.Text)} +`; -function staticLyricHtmlReducer(htmlAccumulator, lyric, index) { - if (layoutManager.tv) { - htmlAccumulator += ``; - } else { - htmlAccumulator += `
${escapeHtml(lyric.Text)}
`; - } return htmlAccumulator; } @@ -96,37 +93,31 @@ export default function (view) { } function renderNoLyricMessage() { - const itemsContainer = view.querySelector('.dynamicLyricsContainer'); + const itemsContainer = view.querySelector('.lyricsContainer'); if (itemsContainer) { - const html = `

${globalize.translate('HeaderNoLyrics')}

`; + const html = `

${globalize.translate('HeaderNoLyrics')}

`; itemsContainer.innerHTML = html; } autoFocuser.autoFocus(); } - function renderDynamicLyrics(lyrics) { - const itemsContainer = view.querySelector('.dynamicLyricsContainer'); + function renderLyrics(lyrics) { + const itemsContainer = view.querySelector('.lyricsContainer'); if (itemsContainer) { - const html = lyrics.reduce(dynamicLyricHtmlReducer, ''); + const html = lyrics.reduce(lyricHtmlReducer, ''); itemsContainer.innerHTML = html; } - const lyricLineArray = itemsContainer.querySelectorAll('.lyricsLine'); + if (isDynamicLyric) { + const lyricLineArray = itemsContainer.querySelectorAll('.lyricsLine'); - // attaches click event listener to change playtime to lyric start - lyricLineArray.forEach(element => { - element.addEventListener('click', () => onLyricClick(element.getAttribute('data-lyrictime'))); - }); + // attaches click event listener to change playtime to lyric start + lyricLineArray.forEach(element => { + element.addEventListener('click', () => onLyricClick(element.getAttribute('data-lyrictime'))); + }); - const currentIndex = getLyricIndex(getCurrentPlayTime(), lyrics); - updateAllLyricLines(currentIndex, savedLyrics); - } - - function renderStaticLyrics(lyrics) { - const itemsContainer = view.querySelector('.dynamicLyricsContainer'); - if (itemsContainer) { - const html = lyrics.reduce(staticLyricHtmlReducer, ''); - itemsContainer.innerHTML = html; + const currentIndex = getLyricIndex(getCurrentPlayTime(), lyrics); + updateAllLyricLines(currentIndex, savedLyrics); } } @@ -135,28 +126,22 @@ export default function (view) { isDynamicLyric = Object.prototype.hasOwnProperty.call(lyrics[0], 'Start'); - if (isDynamicLyric) { - renderDynamicLyrics(savedLyrics); - } else { - renderStaticLyrics(savedLyrics); - } + renderLyrics(savedLyrics); autoFocuser.autoFocus(view); } function getLyrics(serverId, itemId) { const apiClient = ServerConnections.getApiClient(serverId); + const lyricsApi = getLyricsApi(toApi(apiClient)); - return apiClient.ajax({ - url: apiClient.getUrl('Audio/' + itemId + '/Lyrics'), - type: 'GET', - dataType: 'json' - }).then((response) => { - if (!response.Lyrics) { - throw new Error(); - } - return response.Lyrics; - }); + return lyricsApi.getLyrics({ itemId }) + .then(({ data }) => { + if (!data.Lyrics?.length) { + throw new Error('No lyrics returned'); + } + return data.Lyrics; + }); } function bindToPlayer(player) { diff --git a/src/styles/lyrics.scss b/src/styles/lyrics.scss index 0adf81ebd..4e9a7128e 100644 --- a/src/styles/lyrics.scss +++ b/src/styles/lyrics.scss @@ -6,7 +6,7 @@ justify-content: center; } -.dynamicLyricsContainer { +.lyricsContainer { display: flex; flex-direction: column; }