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) => (
-
+
))}
);