fix live analysis multi-device lock
这个提交包含在:
@@ -100,6 +100,7 @@ type MockAppState = {
|
||||
nextVideoId: number;
|
||||
nextTaskId: number;
|
||||
authMeNullResponsesAfterLogin: number;
|
||||
viewerSignalConflictRemaining: number;
|
||||
};
|
||||
|
||||
function trpcResult(json: unknown) {
|
||||
@@ -637,15 +638,24 @@ async function handleMedia(route: Route, state: MockAppState) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.endsWith("/signal")) {
|
||||
state.mediaSession.status = "recording";
|
||||
await fulfillJson(route, { type: "answer", sdp: "mock-answer" });
|
||||
if (path.endsWith("/viewer-signal")) {
|
||||
if (state.viewerSignalConflictRemaining > 0) {
|
||||
state.viewerSignalConflictRemaining -= 1;
|
||||
await route.fulfill({
|
||||
status: 409,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ error: "viewer stream not ready" }),
|
||||
});
|
||||
return;
|
||||
}
|
||||
state.mediaSession.viewerCount = (state.mediaSession.viewerCount || 0) + 1;
|
||||
await fulfillJson(route, { viewerId: `viewer-${state.mediaSession.viewerCount}`, type: "answer", sdp: "mock-answer" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.endsWith("/viewer-signal")) {
|
||||
state.mediaSession.viewerCount = (state.mediaSession.viewerCount || 0) + 1;
|
||||
await fulfillJson(route, { viewerId: `viewer-${state.mediaSession.viewerCount}`, type: "answer", sdp: "mock-answer" });
|
||||
if (path.endsWith("/signal")) {
|
||||
state.mediaSession.status = "recording";
|
||||
await fulfillJson(route, { type: "answer", sdp: "mock-answer" });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -714,6 +724,7 @@ export async function installAppMocks(
|
||||
userName?: string;
|
||||
authMeNullResponsesAfterLogin?: number;
|
||||
liveViewerMode?: boolean;
|
||||
viewerSignalConflictOnce?: boolean;
|
||||
}
|
||||
) {
|
||||
const seededViewerSession = options?.liveViewerMode ? buildMediaSession(buildUser(options?.userName), "其他设备实时分析") : null;
|
||||
@@ -817,6 +828,7 @@ export async function installAppMocks(
|
||||
nextVideoId: 100,
|
||||
nextTaskId: 1,
|
||||
authMeNullResponsesAfterLogin: options?.authMeNullResponsesAfterLogin ?? 0,
|
||||
viewerSignalConflictRemaining: options?.viewerSignalConflictOnce ? 1 : 0,
|
||||
};
|
||||
|
||||
await page.addInitScript(() => {
|
||||
@@ -921,9 +933,12 @@ export async function installAppMocks(
|
||||
localDescription: { type: string; sdp: string } | null = null;
|
||||
remoteDescription: { type: string; sdp: string } | null = null;
|
||||
onconnectionstatechange: (() => void) | null = null;
|
||||
ontrack: ((event: { streams: MediaStream[] }) => void) | null = null;
|
||||
|
||||
addTrack() {}
|
||||
|
||||
addTransceiver() {}
|
||||
|
||||
async createOffer() {
|
||||
return { type: "offer", sdp: "mock-offer" };
|
||||
}
|
||||
@@ -937,6 +952,7 @@ export async function installAppMocks(
|
||||
async setRemoteDescription(description: { type: string; sdp: string }) {
|
||||
this.remoteDescription = description;
|
||||
this.connectionState = "connected";
|
||||
this.ontrack?.({ streams: [new MediaStream()] });
|
||||
this.onconnectionstatechange?.();
|
||||
}
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户