|
|
|
@ -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 (
|
|
|
|
|
<>
|
|
|
|
|
<div className="text-theme-700 dark:text-theme-200 relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1 flex">
|
|
|
|
|
<div className="grow text-xs z-10 self-center ml-2 relative w-full h-4 mr-2">
|
|
|
|
|
<div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden">
|
|
|
|
|
{Name}
|
|
|
|
|
{SeriesName && ` - ${SeriesName}`}
|
|
|
|
|
{enableUser && ` (${UserName})`}
|
|
|
|
|
<div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden" title={streamTitle}>
|
|
|
|
|
{streamTitle}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="self-center text-xs flex justify-end mr-1.5 pl-1">
|
|
|
|
@ -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 }) {
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="grow text-xs z-10 self-center relative w-full h-4">
|
|
|
|
|
<div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden">
|
|
|
|
|
{Name}
|
|
|
|
|
{SeriesName && ` - ${SeriesName}`}
|
|
|
|
|
{enableUser && ` (${UserName})`}
|
|
|
|
|
<div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden" title={streamTitle}>
|
|
|
|
|
{streamTitle}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="self-center text-xs flex justify-end mr-1 z-10">{IsMuted && <BsVolumeMuteFill />}</div>
|
|
|
|
@ -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 }) {
|
|
|
|
|
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
|
|
|
|
|
<span className="absolute left-2 text-xs mt-[2px]">-</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
|
|
|
|
|
<span className="absolute left-2 text-xs mt-[2px]">-</span>
|
|
|
|
|
</div>
|
|
|
|
|
{expandOneStreamToTwoRows && (
|
|
|
|
|
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
|
|
|
|
|
<span className="absolute left-2 text-xs mt-[2px]">-</span>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</>
|
|
|
|
@ -260,15 +277,17 @@ export default function Component({ service }) {
|
|
|
|
|
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
|
|
|
|
|
<span className="absolute left-2 text-xs mt-[2px]">{t("emby.no_active")}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
|
|
|
|
|
<span className="absolute left-2 text-xs mt-[2px]">-</span>
|
|
|
|
|
</div>
|
|
|
|
|
{expandOneStreamToTwoRows && (
|
|
|
|
|
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
|
|
|
|
|
<span className="absolute left-2 text-xs mt-[2px]">-</span>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (playing.length > 0)
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{enableBlocks && <CountBlocks service={service} countData={countData} />}
|
|
|
|
|
<div className="flex flex-col pb-1 mx-1">
|
|
|
|
|
{playing.map((session) => (
|
|
|
|
|
<SessionEntry
|
|
|
|
|
key={session.Id}
|
|
|
|
|
playCommand={(currentSession, command) => handlePlayCommand(currentSession, command)}
|
|
|
|
|
session={session}
|
|
|
|
|
enableUser={enableUser}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{enableBlocks && <CountBlocks service={service} countData={countData} />}
|
|
|
|
|
<div className="flex flex-col pb-1 mx-1">
|
|
|
|
|
{playing.map((session) => (
|
|
|
|
|
<SessionEntry
|
|
|
|
|
key={session.Id}
|
|
|
|
|
playCommand={(currentSession, command) => handlePlayCommand(currentSession, command)}
|
|
|
|
|
session={session}
|
|
|
|
|
enableUser={enableUser}
|
|
|
|
|
showEpisodeNumber={showEpisodeNumber}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (enableBlocks) {
|
|
|
|
|