Sync stage and rail ambient media

This commit is contained in:
DCCONSTRUCTIONS 2026-05-02 11:03:27 +03:00
parent 69eb5260b0
commit adad0bd344
3 changed files with 19 additions and 14 deletions

View File

@ -0,0 +1,11 @@
import type { LauncherServiceView, MediaKind } from "./types";
export const DEFAULT_AMBIENT_MEDIA = "/storage/default.gif";
export const DEFAULT_AMBIENT_MEDIA_KIND: MediaKind = "gif";
export function resolveAmbientMedia(service?: LauncherServiceView): { src: string; kind: MediaKind } {
return {
src: service?.media.ambientVideo ?? DEFAULT_AMBIENT_MEDIA,
kind: service?.media.ambientKind ?? DEFAULT_AMBIENT_MEDIA_KIND,
};
}

View File

@ -1,9 +1,8 @@
import { ChevronRight } from "lucide-react"; import { ChevronRight } from "lucide-react";
import { DEFAULT_AMBIENT_MEDIA, resolveAmbientMedia } from "../../entities/service/media";
import type { LauncherServiceView } from "../../entities/service/types"; import type { LauncherServiceView } from "../../entities/service/types";
import { cn } from "../../shared/lib/cn"; import { cn } from "../../shared/lib/cn";
const DEFAULT_RAIL_MEDIA = "/storage/default.gif";
export function ServiceRail({ export function ServiceRail({
services, services,
selectedServiceId, selectedServiceId,
@ -13,13 +12,12 @@ export function ServiceRail({
selectedServiceId?: string; selectedServiceId?: string;
onSelect: (serviceId: string) => void; onSelect: (serviceId: string) => void;
}) { }) {
const selectedService = services.find((service) => service.id === selectedServiceId) ?? services[0]; const selectedService = services.find((service) => service.id === selectedServiceId);
const railMediaSrc = selectedService?.media.ambientVideo ?? selectedService?.media.coverImage ?? DEFAULT_RAIL_MEDIA; const railMedia = resolveAmbientMedia(selectedService);
const railMediaKind = selectedService?.media.ambientKind ?? selectedService?.media.coverKind;
return ( return (
<div className="service-rail" aria-label="Доступные сервисы"> <div className="service-rail" aria-label="Доступные сервисы">
<RailMedia className="service-rail__backdrop-media" src={railMediaSrc} kind={railMediaKind} /> <RailMedia className="service-rail__backdrop-media" src={railMedia.src} kind={railMedia.kind} />
<div className="service-rail__glass" /> <div className="service-rail__glass" />
<div className="service-rail__scroll"> <div className="service-rail__scroll">
<div className="service-rail__track"> <div className="service-rail__track">
@ -36,7 +34,7 @@ export function ServiceRail({
> >
<RailMedia <RailMedia
className="service-tile__media-asset" className="service-tile__media-asset"
src={service.media.coverImage ?? service.media.ambientVideo ?? DEFAULT_RAIL_MEDIA} src={service.media.coverImage ?? service.media.ambientVideo ?? DEFAULT_AMBIENT_MEDIA}
kind={service.media.coverKind ?? service.media.ambientKind} kind={service.media.coverKind ?? service.media.ambientKind}
/> />
</span> </span>

View File

@ -12,12 +12,11 @@ import {
Network, Network,
Wrench, Wrench,
} from "lucide-react"; } from "lucide-react";
import { resolveAmbientMedia } from "../../entities/service/media";
import type { LauncherServiceView } from "../../entities/service/types"; import type { LauncherServiceView } from "../../entities/service/types";
import { Button } from "../../shared/ui/Button"; import { Button } from "../../shared/ui/Button";
import { ServiceStatusBadge, StatusBadge } from "../../shared/ui/StatusBadge"; import { ServiceStatusBadge, StatusBadge } from "../../shared/ui/StatusBadge";
const DEFAULT_STAGE_MEDIA = "/storage/default.gif";
export function ServiceStage({ export function ServiceStage({
service, service,
hasServices, hasServices,
@ -46,6 +45,7 @@ export function ServiceStage({
const style = { const style = {
"--service-accent": service?.accentColor ?? "#C3FF66", "--service-accent": service?.accentColor ?? "#C3FF66",
} as React.CSSProperties; } as React.CSSProperties;
const ambientMedia = resolveAmbientMedia(service);
const disabledReason = service const disabledReason = service
? service.status === "maintenance" ? service.status === "maintenance"
? "Сервис временно недоступен" ? "Сервис временно недоступен"
@ -60,11 +60,7 @@ export function ServiceStage({
<section className="service-stage" style={style}> <section className="service-stage" style={style}>
<div className="stage-video-shell"> <div className="stage-video-shell">
<div className="stage-video-stream" aria-hidden="true"> <div className="stage-video-stream" aria-hidden="true">
{service?.media.ambientVideo ? ( <StageMedia className="stage-video-gif" src={ambientMedia.src} kind={ambientMedia.kind} />
<StageMedia className="stage-video-gif" src={service.media.ambientVideo} kind={service.media.ambientKind} />
) : (
<img className="stage-video-gif" src={DEFAULT_STAGE_MEDIA} alt="" />
)}
</div> </div>
<div className="stage-video-topline"> <div className="stage-video-topline">