diff --git a/docs/widgets/services/emby.md b/docs/widgets/services/emby.md
index 1d70fdf3..e658d73b 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 0428c622..b6724a15 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 cce45fc3..9cacdf05 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 7fb81088..fc4d57eb 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 f11a689d..9084cbac 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 d224391b..b540c6d7 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) => (
-
+
))}
);