feat: add private profile media and realtime contracts
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import type { VideoTexture } from "three";
|
||||
import type { MediaAuthorizationDecision } from "./types.ts";
|
||||
|
||||
export interface MediaSurfaceBinding {
|
||||
/** All objects are caller-owned. This adapter never obtains or fetches them. */
|
||||
video: HTMLVideoElement;
|
||||
texture: VideoTexture;
|
||||
track?: MediaStreamTrack;
|
||||
}
|
||||
|
||||
export interface MediaSurfaceLifecycle {
|
||||
bind(binding: MediaSurfaceBinding): void;
|
||||
apply(decision: MediaAuthorizationDecision): void;
|
||||
texture(): VideoTexture | null;
|
||||
optedIn(): boolean;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gate an already-created video texture behind a server decision and explicit
|
||||
* viewer consent. `play`, `getUserMedia`, `fetch`, `track.stop`, and
|
||||
* `texture.dispose` are intentionally absent: acquisition and ownership remain
|
||||
* with the caller.
|
||||
*/
|
||||
export function createMediaSurfaceLifecycle(): MediaSurfaceLifecycle {
|
||||
let binding: MediaSurfaceBinding | null = null;
|
||||
let allowed = false;
|
||||
let consent = false;
|
||||
let disposed = false;
|
||||
|
||||
function silence(video: HTMLVideoElement): void {
|
||||
video.autoplay = false;
|
||||
video.muted = true;
|
||||
video.pause();
|
||||
}
|
||||
|
||||
return {
|
||||
bind(next) {
|
||||
if (disposed) throw new Error("media surface lifecycle is disposed");
|
||||
if (binding) silence(binding.video);
|
||||
binding = next;
|
||||
silence(next.video);
|
||||
},
|
||||
apply(decision) {
|
||||
if (disposed) return;
|
||||
allowed = decision.canView && decision.surface.source !== null;
|
||||
consent = decision.optedIn;
|
||||
if (!allowed && binding) silence(binding.video);
|
||||
},
|
||||
texture: () => (!disposed && allowed && consent ? binding?.texture ?? null : null),
|
||||
optedIn: () => consent,
|
||||
dispose() {
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
if (binding) silence(binding.video);
|
||||
binding = null;
|
||||
allowed = false;
|
||||
consent = false;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user