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 { useI18n } from "@homarr/translation/client"; import type { SourcedTracearrItem } from "./source"; type SourcedTracearrStream = SourcedTracearrItem; export function StreamsList({ streams, width, showSource, }: { streams: SourcedTracearrStream[]; width: number; showSource: boolean; }) { const t = useI18n("widget.tracearr"); if (streams.length === 0) { return ( {t("streams.empty")} ); } return ( {streams.map((stream) => ( ))} ); } function StreamCard({ stream, compact, showSource, }: { stream: SourcedTracearrStream; compact: boolean; showSource: boolean; }) { const t = useI18n("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 || showSource) && ( {[stream.player ?? stream.device, showSource ? stream.integrationName : null].filter(Boolean).join(" ยท ")} )} ); }