From 74b0db4a7bda26dd2230b0957152c4482a0933c9 Mon Sep 17 00:00:00 2001 From: Ameer Abdallah Date: Sun, 21 Apr 2024 04:54:52 -0700 Subject: [PATCH] Add showEpisodeNumber and expandOneStreamToTwoRows configuration options to Tautulli and Emby/Jellyfin widgets --- docs/widgets/services/emby.md | 2 + docs/widgets/services/jellyfin.md | 3 ++ docs/widgets/services/plex-tautulli.md | 2 + src/utils/config/service-helpers.js | 9 ++-- src/widgets/emby/component.jsx | 72 ++++++++++++++++---------- src/widgets/tautulli/component.jsx | 60 ++++++++++++++++----- 6 files changed, 102 insertions(+), 46 deletions(-) diff --git a/docs/widgets/services/emby.md b/docs/widgets/services/emby.md index 1d70fdf30..e658d73b7 100644 --- a/docs/widgets/services/emby.md +++ b/docs/widgets/services/emby.md @@ -17,4 +17,6 @@ widget: enableBlocks: true # optional, defaults to false enableNowPlaying: true # optional, defaults to true enableUser: true # optional, defaults to false + showEpisodeNumber: true # optional, defaults to false + expandOneStreamToTwoRows: false # optional, defaults to true ``` diff --git a/docs/widgets/services/jellyfin.md b/docs/widgets/services/jellyfin.md index 0428c622a..b6724a152 100644 --- a/docs/widgets/services/jellyfin.md +++ b/docs/widgets/services/jellyfin.md @@ -16,4 +16,7 @@ widget: key: apikeyapikeyapikeyapikeyapikey enableBlocks: true # optional, defaults to false enableNowPlaying: true # optional, defaults to true + enableUser: true # optional, defaults to false + showEpisodeNumber: true # optional, defaults to false + expandOneStreamToTwoRows: false # optional, defaults to true ``` diff --git a/docs/widgets/services/plex-tautulli.md b/docs/widgets/services/plex-tautulli.md index cce45fc3e..9cacdf057 100644 --- a/docs/widgets/services/plex-tautulli.md +++ b/docs/widgets/services/plex-tautulli.md @@ -15,4 +15,6 @@ widget: url: http://tautulli.host.or.ip key: apikeyapikeyapikeyapikeyapikey enableUser: true # optional, defaults to false + showEpisodeNumber: true # optional, defaults to false + expandOneStreamToTwoRows: false # optional, defaults to true ``` diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js index 7fb810881..6595b968d 100644 --- a/src/utils/config/service-helpers.js +++ b/src/utils/config/service-helpers.js @@ -395,6 +395,8 @@ export function cleanServiceGroups(groups) { // emby, jellyfin, tautulli enableUser, + expandOneStreamToTwoRows, + showEpisodeNumber, // glances, pihole version, @@ -520,11 +522,10 @@ export function cleanServiceGroups(groups) { if (["emby", "jellyfin"].includes(type)) { if (enableBlocks !== undefined) cleanedService.widget.enableBlocks = JSON.parse(enableBlocks); if (enableNowPlaying !== undefined) cleanedService.widget.enableNowPlaying = JSON.parse(enableNowPlaying); - if (enableUser !== undefined) { - cleanedService.widget.enableUser = !!JSON.parse(enableUser); - } } - if (["tautulli"].includes(type)) { + if (["emby", "jellyfin", "tautulli"].includes(type)) { + if (expandOneStreamToTwoRows !== undefined) cleanedService.widget.expandOneStreamToTwoRows = !!JSON.parse(expandOneStreamToTwoRows); + if (showEpisodeNumber !== undefined) cleanedService.widget.showEpisodeNumber = !!JSON.parse(showEpisodeNumber); if (enableUser !== undefined) { cleanedService.widget.enableUser = !!JSON.parse(enableUser); } diff --git a/src/widgets/emby/component.jsx b/src/widgets/emby/component.jsx index f11a689d5..086f5bfef 100644 --- a/src/widgets/emby/component.jsx +++ b/src/widgets/emby/component.jsx @@ -27,9 +27,20 @@ function ticksToString(ticks) { return parts.map((part) => part.toString().padStart(2, "0")).join(":"); } -function SingleSessionEntry({ playCommand, session, enableUser }) { +function generateSeriesTitle(session, showEpisodeNumber) { + const { + NowPlayingItem: { Name, SeriesName, Type, ParentIndexNumber, IndexNumber }, + } = session; + + if (Type === "Episode" && showEpisodeNumber) { + return `${SeriesName} - S${ParentIndexNumber.toString().padStart(2, "0")}E${IndexNumber.toString().padStart(2, "0")} - ${Name}`; + } + + return `${Name}${SeriesName ? ` - ${SeriesName}` : ""}`; +} + +function SingleSessionEntry({ playCommand, session, enableUser, showEpisodeNumber }) { const { - NowPlayingItem: { Name, SeriesName }, PlayState: { PositionTicks, IsPaused, IsMuted }, UserName, } = session; @@ -43,13 +54,13 @@ function SingleSessionEntry({ playCommand, session, enableUser }) { const percent = Math.min(1, PositionTicks / RunTimeTicks) * 100; + const seriesTitle = generateSeriesTitle(session, enableUser, showEpisodeNumber); return ( <>
- {Name} - {SeriesName && ` - ${SeriesName}`} + {seriesTitle} {enableUser && ` (${UserName})`}
@@ -99,9 +110,8 @@ function SingleSessionEntry({ playCommand, session, enableUser }) { ); } -function SessionEntry({ playCommand, session, enableUser }) { +function SessionEntry({ playCommand, session, enableUser, showEpisodeNumber }) { const { - NowPlayingItem: { Name, SeriesName }, PlayState: { PositionTicks, IsPaused, IsMuted }, UserName, } = session; @@ -113,6 +123,8 @@ function SessionEntry({ playCommand, session, enableUser }) { IsVideoDirect: true, }; // if no transcodinginfo its videodirect + const seriesTitle = generateSeriesTitle(session, enableUser, showEpisodeNumber); + const percent = Math.min(1, PositionTicks / RunTimeTicks) * 100; return ( @@ -143,8 +155,7 @@ function SessionEntry({ playCommand, session, enableUser }) {
- {Name} - {SeriesName && ` - ${SeriesName}`} + {seriesTitle} {enableUser && ` (${UserName})`}
@@ -219,7 +230,9 @@ export default function Component({ service }) { const enableBlocks = service.widget?.enableBlocks; const enableNowPlaying = service.widget?.enableNowPlaying ?? true; - const enableUser = !!service.widget?.enableUser; + const enableUser = !!service.widget?.enableUser; // default is true + const expandOneStreamToTwoRows = service.widget?.expandOneStreamToTwoRows !== false; // default is true + const showEpisodeNumber = !!service.widget?.showEpisodeNumber; // default is false if (!sessionsData || !countData) { return ( @@ -260,15 +273,17 @@ export default function Component({ service }) {
{t("emby.no_active")}
-
+ {expandOneStreamToTwoRows && ( +
- -
+
+ )} ); } - if (playing.length === 1) { + if (expandOneStreamToTwoRows && playing.length === 1) { const session = playing[0]; return ( <> @@ -278,28 +293,29 @@ export default function Component({ service }) { playCommand={(currentSession, command) => handlePlayCommand(currentSession, command)} session={session} enableUser={enableUser} + showEpisodeNumber={showEpisodeNumber} /> ); } - if (playing.length > 0) - return ( - <> - {enableBlocks && } -
- {playing.map((session) => ( - handlePlayCommand(currentSession, command)} - session={session} - enableUser={enableUser} - /> - ))} -
- - ); + return ( + <> + {enableBlocks && } +
+ {playing.map((session) => ( + handlePlayCommand(currentSession, command)} + session={session} + enableUser={enableUser} + showEpisodeNumber={showEpisodeNumber} + /> + ))} +
+ + ); } if (enableBlocks) { diff --git a/src/widgets/tautulli/component.jsx b/src/widgets/tautulli/component.jsx index d224391b7..2258a8d39 100644 --- a/src/widgets/tautulli/component.jsx +++ b/src/widgets/tautulli/component.jsx @@ -25,16 +25,34 @@ function millisecondsToString(milliseconds) { return parts.map((part) => part.toString().padStart(2, "0")).join(":"); } -function SingleSessionEntry({ session, enableUser }) { - const { full_title, duration, view_offset, progress_percent, state, video_decision, audio_decision, username } = - session; +function generateStreamTitle(session, showEpisodeNumber) { + const { media_type, parent_media_index, media_index, title, grandparent_title, full_title } = session; + if (media_type === "episode" && showEpisodeNumber) { + return `${grandparent_title}: S${parent_media_index.toString().padStart(2, "0")} ยท E${media_index.toString().padStart(2, "0")} - ${title}`; + } + + return full_title; +} + +function SingleSessionEntry({ session, enableUser, showEpisodeNumber }) { + const { + duration, + view_offset, + progress_percent, + state, + video_decision, + audio_decision, + username + } = session; + + const stream_title = generateStreamTitle(session, showEpisodeNumber) return ( <>
- {full_title} + {stream_title} {enableUser && ` (${username})`}
@@ -78,8 +96,17 @@ function SingleSessionEntry({ session, enableUser }) { ); } -function SessionEntry({ session, enableUser }) { - const { full_title, view_offset, progress_percent, state, video_decision, audio_decision, username } = session; +function SessionEntry({ session, enableUser, showEpisodeNumber }) { + const { + view_offset, + progress_percent, + state, + video_decision, + audio_decision, + username + } = session; + + const stream_title = generateStreamTitle(session, showEpisodeNumber) return (
@@ -99,7 +126,7 @@ function SessionEntry({ session, enableUser }) {
- {full_title} + {stream_title} {enableUser && ` (${username})`}
@@ -156,26 +183,31 @@ export default function Component({ service }) { return 0; }); + const expandOneStreamToTwoRows = service.widget?.expandOneStreamToTwoRows !== false; // default is true + if (playing.length === 0) { return (
{t("tautulli.no_active")}
-
- - -
+ {expandOneStreamToTwoRows && ( +
+ - +
+ )}
); } - const enableUser = !!service.widget?.enableUser; + const enableUser = !!service.widget?.enableUser; // default is false + const showEpisodeNumber = !!service.widget?.showEpisodeNumber; // default is false - if (playing.length === 1) { + if (expandOneStreamToTwoRows && playing.length === 1) { const session = playing[0]; return (
- +
); } @@ -183,7 +215,7 @@ export default function Component({ service }) { return (
{playing.map((session) => ( - + ))}
);