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..fc4d57eb9 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,14 +522,13 @@ 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 (enableUser !== undefined) { - cleanedService.widget.enableUser = !!JSON.parse(enableUser); - } + 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); } if (["sonarr", "radarr"].includes(type)) { if (enableQueue !== undefined) cleanedService.widget.enableQueue = JSON.parse(enableQueue); diff --git a/src/widgets/emby/component.jsx b/src/widgets/emby/component.jsx index f11a689d5..9084cbac2 100644 --- a/src/widgets/emby/component.jsx +++ b/src/widgets/emby/component.jsx @@ -27,12 +27,28 @@ function ticksToString(ticks) { return parts.map((part) => part.toString().padStart(2, "0")).join(":"); } -function SingleSessionEntry({ playCommand, session, enableUser }) { +function generateStreamTitle(session, enableUser, showEpisodeNumber) { const { - NowPlayingItem: { Name, SeriesName }, - PlayState: { PositionTicks, IsPaused, IsMuted }, + NowPlayingItem: { Name, SeriesName, Type, ParentIndexNumber, IndexNumber }, UserName, } = session; + let streamTitle = ""; + + if (Type === "Episode" && showEpisodeNumber) { + const seasonStr = `S${ParentIndexNumber.toString().padStart(2, "0")}`; + const episodeStr = `E${IndexNumber.toString().padStart(2, "0")}`; + streamTitle = `${SeriesName}: ${seasonStr} · ${episodeStr} - ${Name}`; + } else { + streamTitle = `${Name}${SeriesName ? ` - ${SeriesName}` : ""}`; + } + + return enableUser ? `${streamTitle} (${UserName})` : streamTitle; +} + +function SingleSessionEntry({ playCommand, session, enableUser, showEpisodeNumber }) { + const { + PlayState: { PositionTicks, IsPaused, IsMuted }, + } = session; const RunTimeTicks = session.NowPlayingItem?.RunTimeTicks ?? session.NowPlayingItem?.CurrentProgram?.RunTimeTicks ?? 0; @@ -43,14 +59,13 @@ function SingleSessionEntry({ playCommand, session, enableUser }) { const percent = Math.min(1, PositionTicks / RunTimeTicks) * 100; + const streamTitle = generateStreamTitle(session, enableUser, showEpisodeNumber); return ( <>
-
- {Name} - {SeriesName && ` - ${SeriesName}`} - {enableUser && ` (${UserName})`} +
+ {streamTitle}
@@ -99,11 +114,9 @@ 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; const RunTimeTicks = @@ -113,6 +126,8 @@ function SessionEntry({ playCommand, session, enableUser }) { IsVideoDirect: true, }; // if no transcodinginfo its videodirect + const streamTitle = generateStreamTitle(session, enableUser, showEpisodeNumber); + const percent = Math.min(1, PositionTicks / RunTimeTicks) * 100; return ( @@ -142,10 +157,8 @@ function SessionEntry({ playCommand, session, enableUser }) { )}
-
- {Name} - {SeriesName && ` - ${SeriesName}`} - {enableUser && ` (${UserName})`} +
+ {streamTitle}
{IsMuted && }
@@ -219,7 +232,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 false + const expandOneStreamToTwoRows = service.widget?.expandOneStreamToTwoRows !== false; // default is true + const showEpisodeNumber = !!service.widget?.showEpisodeNumber; // default is false if (!sessionsData || !countData) { return ( @@ -230,9 +245,11 @@ export default function Component({ service }) {
-
-
- - -
+ {expandOneStreamToTwoRows && ( +
+ - +
+ )}
)} @@ -260,15 +277,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 +297,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..b540c6d70 100644 --- a/src/widgets/tautulli/component.jsx +++ b/src/widgets/tautulli/component.jsx @@ -25,17 +25,31 @@ 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, enableUser, showEpisodeNumber) { + let stream_title = ""; + const { media_type, parent_media_index, media_index, title, grandparent_title, full_title, friendly_name } = session; + if (media_type === "episode" && showEpisodeNumber) { + const season_str = `S${parent_media_index.toString().padStart(2, "0")}`; + const episode_str = `E${media_index.toString().padStart(2, "0")}`; + stream_title = `${grandparent_title}: ${season_str} · ${episode_str} - ${title}`; + } else { + stream_title = full_title; + } + + return enableUser ? `${stream_title} (${friendly_name})` : stream_title; +} + +function SingleSessionEntry({ session, enableUser, showEpisodeNumber }) { + const { duration, view_offset, progress_percent, state, video_decision, audio_decision } = session; + + const stream_title = generateStreamTitle(session, enableUser, showEpisodeNumber); return ( <>
-
- {full_title} - {enableUser && ` (${username})`} +
+ {stream_title}
@@ -78,8 +92,10 @@ 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 } = session; + + const stream_title = generateStreamTitle(session, enableUser, showEpisodeNumber); return (
@@ -98,9 +114,8 @@ function SessionEntry({ session, enableUser }) { )}
-
- {full_title} - {enableUser && ` (${username})`} +
+ {stream_title}
@@ -129,6 +144,10 @@ export default function Component({ service }) { refreshInterval: 5000, }); + const enableUser = !!service.widget?.enableUser; // default is false + const expandOneStreamToTwoRows = service.widget?.expandOneStreamToTwoRows !== false; // default is true + const showEpisodeNumber = !!service.widget?.showEpisodeNumber; // default is false + if (activityError || (activityData && Object.keys(activityData.response.data).length === 0)) { return ; } @@ -139,9 +158,11 @@ export default function Component({ service }) {
-
-
- - -
+ {expandOneStreamToTwoRows && ( +
+ - +
+ )}
); } @@ -162,20 +183,20 @@ export default function Component({ service }) {
{t("tautulli.no_active")}
-
- - -
+ {expandOneStreamToTwoRows && ( +
+ - +
+ )}
); } - const enableUser = !!service.widget?.enableUser; - - if (playing.length === 1) { + if (expandOneStreamToTwoRows && playing.length === 1) { const session = playing[0]; return (
- +
); } @@ -183,7 +204,12 @@ export default function Component({ service }) { return (
{playing.map((session) => ( - + ))}
);