import { Badge, Box, Group, Paper, Progress, Stack, Text, Tooltip } from "@mantine/core"; import { IconPlayerPause, IconPlayerPlay } from "@tabler/icons-react"; import { formatDuration } from "@homarr/common"; import type { TracearrStream } from "@homarr/integrations/types"; import { useScopedI18n } from "@homarr/translation/client"; export function StreamsList({ streams, width }: { streams: TracearrStream[]; width: number }) { const t = useScopedI18n("widget.tracearr"); if (streams.length === 0) { return ( {t("streams.empty")} ); } return ( {streams.map((stream) => ( ))} ); } function StreamCard({ stream, compact }: { stream: TracearrStream; compact: boolean }) { const t = useScopedI18n("widget.tracearr"); const progressPercent = stream.durationMs && stream.durationMs > 0 ? (stream.progressMs / stream.durationMs) * 100 : 0; const mediaLabel = stream.mediaType === "episode" && stream.showTitle ? `${stream.showTitle} - S${stream.seasonNumber ?? 0}E${stream.episodeNumber ?? 0} - ${stream.mediaTitle}` : stream.mediaTitle; const videoDecisionLabel = stream.videoDecision === "directplay" ? t("streams.videoDecision.directPlay") : stream.videoDecision === "transcode" ? t("streams.videoDecision.transcode") : stream.videoDecision === "copy" ? t("streams.videoDecision.directStream") : null; return ( {stream.posterUrl && ( )} {stream.state === "playing" ? ( ) : ( )} {stream.username} {stream.resolution && ( {stream.resolution} )} {videoDecisionLabel && ( {videoDecisionLabel} )} {mediaLabel} {stream.durationMs && stream.durationMs > 0 && ( {formatDuration(stream.progressMs)} / {formatDuration(stream.durationMs)} )} {stream.device && ( {stream.player ?? stream.device} )} ); }