fix(im): 清理 RTC 媒体元素卸载时的 srcObject
- 对齐 Vue3 管理后台 63dfc5e 的 RTC 媒体元素处理 - useMediaStreamElement 改为 callback ref 闭包保存当前元素 - 组件卸载或 ref 置空时清理旧 video/audio 元素的 srcObject,避免流关闭后画面残留 - 同步适配 web-antd、web-ele、web-antdv-next 验证: - pnpm -F @vben/web-antd run typecheck - pnpm -F @vben/web-ele run typecheck - web-antdv-next 仍为既有 55 个类型错误,无 RTC 新增错误migration
parent
953e7c1502
commit
0a76bed471
|
|
@ -1,4 +1,4 @@
|
|||
import { ref, type VNodeRef, watch } from 'vue'
|
||||
import { type VNodeRef, watch } from 'vue'
|
||||
|
||||
/**
|
||||
* 把响应式 MediaStream 挂到 `<video>` / `<audio>` 元素的 srcObject 上;
|
||||
|
|
@ -7,21 +7,34 @@ import { ref, type VNodeRef, watch } from 'vue'
|
|||
export function useMediaStreamElement<T extends HTMLMediaElement>(
|
||||
streamSource: () => MediaStream | null | undefined
|
||||
): VNodeRef {
|
||||
const elRef = ref<T>()
|
||||
const syncStream = (stream = streamSource()) => {
|
||||
if (elRef.value) {
|
||||
elRef.value.srcObject = stream || null
|
||||
let el: T | null = null
|
||||
let currentStream: MediaStream | null | undefined
|
||||
|
||||
const syncStream = () => {
|
||||
if (el) {
|
||||
el.srcObject = currentStream || null
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
streamSource,
|
||||
(stream) => {
|
||||
syncStream(stream)
|
||||
currentStream = stream
|
||||
syncStream()
|
||||
},
|
||||
{ flush: 'post', immediate: true }
|
||||
)
|
||||
return (el) => {
|
||||
elRef.value = el instanceof HTMLMediaElement ? (el as T) : undefined
|
||||
syncStream()
|
||||
|
||||
return (value) => {
|
||||
if (value instanceof HTMLMediaElement) {
|
||||
el = value as T
|
||||
syncStream()
|
||||
return
|
||||
}
|
||||
|
||||
if (el) {
|
||||
el.srcObject = null
|
||||
}
|
||||
el = null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ref, type VNodeRef, watch } from 'vue'
|
||||
import { type VNodeRef, watch } from 'vue'
|
||||
|
||||
/**
|
||||
* 把响应式 MediaStream 挂到 `<video>` / `<audio>` 元素的 srcObject 上;
|
||||
|
|
@ -7,21 +7,34 @@ import { ref, type VNodeRef, watch } from 'vue'
|
|||
export function useMediaStreamElement<T extends HTMLMediaElement>(
|
||||
streamSource: () => MediaStream | null | undefined
|
||||
): VNodeRef {
|
||||
const elRef = ref<T>()
|
||||
const syncStream = (stream = streamSource()) => {
|
||||
if (elRef.value) {
|
||||
elRef.value.srcObject = stream || null
|
||||
let el: T | null = null
|
||||
let currentStream: MediaStream | null | undefined
|
||||
|
||||
const syncStream = () => {
|
||||
if (el) {
|
||||
el.srcObject = currentStream || null
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
streamSource,
|
||||
(stream) => {
|
||||
syncStream(stream)
|
||||
currentStream = stream
|
||||
syncStream()
|
||||
},
|
||||
{ flush: 'post', immediate: true }
|
||||
)
|
||||
return (el) => {
|
||||
elRef.value = el instanceof HTMLMediaElement ? (el as T) : undefined
|
||||
syncStream()
|
||||
|
||||
return (value) => {
|
||||
if (value instanceof HTMLMediaElement) {
|
||||
el = value as T
|
||||
syncStream()
|
||||
return
|
||||
}
|
||||
|
||||
if (el) {
|
||||
el.srcObject = null
|
||||
}
|
||||
el = null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ref, type VNodeRef, watch } from 'vue'
|
||||
import { type VNodeRef, watch } from 'vue'
|
||||
|
||||
/**
|
||||
* 把响应式 MediaStream 挂到 `<video>` / `<audio>` 元素的 srcObject 上;
|
||||
|
|
@ -7,21 +7,34 @@ import { ref, type VNodeRef, watch } from 'vue'
|
|||
export function useMediaStreamElement<T extends HTMLMediaElement>(
|
||||
streamSource: () => MediaStream | null | undefined
|
||||
): VNodeRef {
|
||||
const elRef = ref<T>()
|
||||
const syncStream = (stream = streamSource()) => {
|
||||
if (elRef.value) {
|
||||
elRef.value.srcObject = stream || null
|
||||
let el: T | null = null
|
||||
let currentStream: MediaStream | null | undefined
|
||||
|
||||
const syncStream = () => {
|
||||
if (el) {
|
||||
el.srcObject = currentStream || null
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
streamSource,
|
||||
(stream) => {
|
||||
syncStream(stream)
|
||||
currentStream = stream
|
||||
syncStream()
|
||||
},
|
||||
{ flush: 'post', immediate: true }
|
||||
)
|
||||
return (el) => {
|
||||
elRef.value = el instanceof HTMLMediaElement ? (el as T) : undefined
|
||||
syncStream()
|
||||
|
||||
return (value) => {
|
||||
if (value instanceof HTMLMediaElement) {
|
||||
el = value as T
|
||||
syncStream()
|
||||
return
|
||||
}
|
||||
|
||||
if (el) {
|
||||
el.srcObject = null
|
||||
}
|
||||
el = null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue