视频会议
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
<view v-if="!isVoiceMode" class="remote-stage">
|
<view v-if="!isVoiceMode" class="remote-stage">
|
||||||
<VideoTile
|
<VideoTile
|
||||||
v-if="primaryTile"
|
v-if="primaryTile"
|
||||||
class="main-video"
|
class="main-video clean-video-tile"
|
||||||
:user-id="primaryTile.userId"
|
:user-id="primaryTile.userId"
|
||||||
:name="primaryTile.name"
|
:name="primaryTile.name"
|
||||||
:is-local="primaryTile.isLocal"
|
:is-local="primaryTile.isLocal"
|
||||||
@@ -38,24 +38,24 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="!isVoiceMode && selfTile && primaryTile && !primaryTile.isLocal" class="self-preview">
|
<view v-if="!isVoiceMode && secondaryTile" class="self-preview" @click="swapPrimaryTile">
|
||||||
<VideoTile
|
<VideoTile
|
||||||
class="self-video"
|
class="self-video clean-video-tile"
|
||||||
:user-id="selfTile.userId"
|
:user-id="secondaryTile.userId"
|
||||||
:name="selfTile.name"
|
:name="secondaryTile.name"
|
||||||
:is-local="selfTile.isLocal"
|
:is-local="secondaryTile.isLocal"
|
||||||
:is-host="selfTile.isHost"
|
:is-host="secondaryTile.isHost"
|
||||||
:audio-enabled="selfTile.audioEnabled"
|
:audio-enabled="secondaryTile.audioEnabled"
|
||||||
:video-enabled="selfTile.videoEnabled"
|
:video-enabled="secondaryTile.videoEnabled"
|
||||||
:audio-track="selfTile.audioTrack"
|
:audio-track="secondaryTile.audioTrack"
|
||||||
:video-track="selfTile.videoTrack"
|
:video-track="secondaryTile.videoTrack"
|
||||||
:is-speaking="!!speakingMap[selfTile.userId]"
|
:is-speaking="!!speakingMap[secondaryTile.userId]"
|
||||||
:compact="true"
|
:compact="true"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="!isVoiceMode" class="video-topbar">
|
<view v-if="!isVoiceMode" class="video-topbar">
|
||||||
<view class="top-window-icon"></view>
|
<view class="top-window-icon" @click="swapPrimaryTile"></view>
|
||||||
<text class="top-duration">{{ durationText }}</text>
|
<text class="top-duration">{{ durationText }}</text>
|
||||||
<text class="top-plus">+</text>
|
<text class="top-plus">+</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -127,6 +127,7 @@ const leaving = ref(false)
|
|||||||
const startedAt = ref(0)
|
const startedAt = ref(0)
|
||||||
const nowTs = ref(Date.now())
|
const nowTs = ref(Date.now())
|
||||||
const ended = ref(false)
|
const ended = ref(false)
|
||||||
|
const preferSelfMain = ref(false)
|
||||||
let timerHandle = null
|
let timerHandle = null
|
||||||
let stateStopWatch = null
|
let stateStopWatch = null
|
||||||
let videoRetryHandle = null
|
let videoRetryHandle = null
|
||||||
@@ -244,7 +245,16 @@ const tiles = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const selfTile = computed(() => tiles.value.find(t => t.isLocal) || null)
|
const selfTile = computed(() => tiles.value.find(t => t.isLocal) || null)
|
||||||
const primaryTile = computed(() => tiles.value.find(t => !t.isLocal && t.videoTrack) || selfTile.value || tiles.value.find(t => !t.isLocal))
|
const remoteTile = computed(() => tiles.value.find(t => !t.isLocal && t.videoTrack) || tiles.value.find(t => !t.isLocal) || null)
|
||||||
|
const primaryTile = computed(() => {
|
||||||
|
if (preferSelfMain.value && selfTile.value) return selfTile.value
|
||||||
|
return remoteTile.value || selfTile.value
|
||||||
|
})
|
||||||
|
const secondaryTile = computed(() => {
|
||||||
|
if (!primaryTile.value) return null
|
||||||
|
if (primaryTile.value.isLocal) return remoteTile.value
|
||||||
|
return selfTile.value
|
||||||
|
})
|
||||||
const voicePeer = computed(() => participants.value.find(p => !sameUser(p.user_id, myUserId.value)) || null)
|
const voicePeer = computed(() => participants.value.find(p => !sameUser(p.user_id, myUserId.value)) || null)
|
||||||
const voiceName = computed(() => {
|
const voiceName = computed(() => {
|
||||||
if (voicePeer.value?.user_name) return voicePeer.value.user_name
|
if (voicePeer.value?.user_name) return voicePeer.value.user_name
|
||||||
@@ -418,6 +428,11 @@ const scheduleVideoRetry = () => {
|
|||||||
}, 800)
|
}, 800)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const swapPrimaryTile = () => {
|
||||||
|
if (!selfTile.value || !remoteTile.value) return
|
||||||
|
preferSelfMain.value = !preferSelfMain.value
|
||||||
|
}
|
||||||
|
|
||||||
const onMicToggle = async () => {
|
const onMicToggle = async () => {
|
||||||
if (audioLoading.value || leaving.value) return
|
if (audioLoading.value || leaving.value) return
|
||||||
audioLoading.value = true
|
audioLoading.value = true
|
||||||
@@ -772,8 +787,8 @@ onUnload(() => {
|
|||||||
}
|
}
|
||||||
.control-btn,
|
.control-btn,
|
||||||
.hangup-btn {
|
.hangup-btn {
|
||||||
width: 124rpx;
|
width: 140rpx;
|
||||||
height: 124rpx;
|
height: 140rpx;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -785,8 +800,8 @@ onUnload(() => {
|
|||||||
box-shadow: 0 10rpx 26rpx rgba(0, 0, 0, 0.18);
|
box-shadow: 0 10rpx 26rpx rgba(0, 0, 0, 0.18);
|
||||||
}
|
}
|
||||||
.dark-btn {
|
.dark-btn {
|
||||||
width: 112rpx;
|
width: 132rpx;
|
||||||
height: 112rpx;
|
height: 132rpx;
|
||||||
background: rgba(22, 43, 105, 0.86);
|
background: rgba(22, 43, 105, 0.86);
|
||||||
border: 1rpx solid rgba(255, 255, 255, 0.06);
|
border: 1rpx solid rgba(255, 255, 255, 0.06);
|
||||||
box-shadow: inset 0 0 0 2rpx rgba(255, 255, 255, 0.04);
|
box-shadow: inset 0 0 0 2rpx rgba(255, 255, 255, 0.04);
|
||||||
@@ -795,22 +810,22 @@ onUnload(() => {
|
|||||||
opacity: 0.94;
|
opacity: 0.94;
|
||||||
}
|
}
|
||||||
.hangup-btn {
|
.hangup-btn {
|
||||||
width: 132rpx;
|
width: 150rpx;
|
||||||
height: 132rpx;
|
height: 150rpx;
|
||||||
background: #ff2f3f;
|
background: #ff2f3f;
|
||||||
box-shadow: 0 14rpx 36rpx rgba(255, 47, 63, 0.38);
|
box-shadow: 0 14rpx 36rpx rgba(255, 47, 63, 0.38);
|
||||||
}
|
}
|
||||||
.control-image {
|
.control-image {
|
||||||
width: 58rpx;
|
width: 76rpx;
|
||||||
height: 58rpx;
|
height: 76rpx;
|
||||||
}
|
}
|
||||||
.dark-btn .control-image {
|
.dark-btn .control-image {
|
||||||
width: 50rpx;
|
width: 68rpx;
|
||||||
height: 50rpx;
|
height: 68rpx;
|
||||||
}
|
}
|
||||||
.hangup-image {
|
.hangup-image {
|
||||||
width: 74rpx;
|
width: 92rpx;
|
||||||
height: 74rpx;
|
height: 92rpx;
|
||||||
}
|
}
|
||||||
.control-label {
|
.control-label {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
@@ -821,4 +836,10 @@ onUnload(() => {
|
|||||||
.loading {
|
.loading {
|
||||||
opacity: 0.68;
|
opacity: 0.68;
|
||||||
}
|
}
|
||||||
|
.clean-video-tile :deep(.footer) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.clean-video-tile :deep(.tag-self) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user