mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-11 18:01:59 +00:00
Add voice activity ui (#8460)
Some checks are pending
CI / build (push) Waiting to run
CI / svelte-check (push) Blocked by required conditions
CI / formatting (push) Blocked by required conditions
CI / test (push) Blocked by required conditions
CI / uitest (push) Waiting to run
CI / uitest-pg (push) Waiting to run
CI / uitest-qms (push) Waiting to run
CI / uitest-workspaces (push) Waiting to run
CI / docker-build (push) Blocked by required conditions
CI / dist-build (push) Blocked by required conditions
Some checks are pending
CI / build (push) Waiting to run
CI / svelte-check (push) Blocked by required conditions
CI / formatting (push) Blocked by required conditions
CI / test (push) Blocked by required conditions
CI / uitest (push) Waiting to run
CI / uitest-pg (push) Waiting to run
CI / uitest-qms (push) Waiting to run
CI / uitest-workspaces (push) Waiting to run
CI / docker-build (push) Blocked by required conditions
CI / dist-build (push) Blocked by required conditions
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com> Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com> Co-authored-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
parent
66325de693
commit
f81d1d66f3
@ -17,8 +17,11 @@
|
|||||||
import { Avatar, personByIdStore } from '@hcengineering/contact-resources'
|
import { Avatar, personByIdStore } from '@hcengineering/contact-resources'
|
||||||
import { Ref } from '@hcengineering/core'
|
import { Ref } from '@hcengineering/core'
|
||||||
import { Loading } from '@hcengineering/ui'
|
import { Loading } from '@hcengineering/ui'
|
||||||
import love from '../plugin'
|
|
||||||
|
import { currentRoomAudioLevels } from '../utils'
|
||||||
import MicDisabled from './icons/MicDisabled.svelte'
|
import MicDisabled from './icons/MicDisabled.svelte'
|
||||||
|
import { tweened } from 'svelte/motion'
|
||||||
|
import { elasticInOut } from 'svelte/easing'
|
||||||
|
|
||||||
export let _id: string
|
export let _id: string
|
||||||
export let name: string
|
export let name: string
|
||||||
@ -29,6 +32,12 @@
|
|||||||
let parent: HTMLDivElement
|
let parent: HTMLDivElement
|
||||||
let activeTrack: boolean = false
|
let activeTrack: boolean = false
|
||||||
|
|
||||||
|
let level: number = 0
|
||||||
|
const speakers = tweened(0, {
|
||||||
|
duration: 5,
|
||||||
|
easing: elasticInOut
|
||||||
|
})
|
||||||
|
|
||||||
export function appendChild (track: HTMLMediaElement): void {
|
export function appendChild (track: HTMLMediaElement): void {
|
||||||
const video = parent.querySelector('.video')
|
const video = parent.querySelector('.video')
|
||||||
if (video != null) {
|
if (video != null) {
|
||||||
@ -53,9 +62,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$: user = $personByIdStore.get(_id as Ref<Person>)
|
$: user = $personByIdStore.get(_id as Ref<Person>)
|
||||||
|
|
||||||
|
$: speach = $currentRoomAudioLevels.get(_id as Ref<Person>) ?? 0
|
||||||
|
let tspeach: number = 0
|
||||||
|
$: if ((speach > 0 && speach > tspeach) || (tspeach > 0 && speach <= 0)) {
|
||||||
|
void speakers.set(speach > 0.3 ? 0.3 : speach, { duration: 50, easing: elasticInOut })
|
||||||
|
}
|
||||||
|
speakers.subscribe((sp) => {
|
||||||
|
tspeach = sp > 0 ? sp : 0
|
||||||
|
level = tspeach
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id={_id} class="parent">
|
<div id={_id} class="parent" style:--border-opacity={level}>
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="overflow-label">{formatName(name)}</span>
|
<span class="overflow-label">{formatName(name)}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -109,12 +128,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.parent {
|
.parent {
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
height: max-content;
|
height: max-content;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
|
background-color: black;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
|
||||||
.label,
|
.label,
|
||||||
.icon {
|
.icon {
|
||||||
@ -127,7 +147,6 @@
|
|||||||
color: rgba(0, 0, 0, 0.75);
|
color: rgba(0, 0, 0, 0.75);
|
||||||
background-color: rgba(255, 255, 255, 0.5);
|
background-color: rgba(255, 255, 255, 0.5);
|
||||||
backdrop-filter: blur(3px);
|
backdrop-filter: blur(3px);
|
||||||
z-index: 1;
|
|
||||||
}
|
}
|
||||||
.label {
|
.label {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -151,5 +170,25 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&::after,
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
content: '';
|
||||||
|
background-color: var(--theme-caption-color);
|
||||||
|
opacity: var(--border-opacity, 0);
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
&::after {
|
||||||
|
inset: -0.125rem;
|
||||||
|
width: calc(100% + 0.25rem);
|
||||||
|
height: calc(100% + 0.25rem);
|
||||||
|
border-radius: calc(0.75rem + 0.125rem);
|
||||||
|
}
|
||||||
|
&::before {
|
||||||
|
inset: -0.25rem;
|
||||||
|
width: calc(100% + 0.5rem);
|
||||||
|
height: calc(100% + 0.5rem);
|
||||||
|
border-radius: calc(0.75rem + 0.25rem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -373,7 +373,7 @@
|
|||||||
<Scroller
|
<Scroller
|
||||||
bind:divScroll
|
bind:divScroll
|
||||||
noStretch
|
noStretch
|
||||||
padding={'0 .5rem'}
|
padding={'.25rem .5rem 0'}
|
||||||
containerName={'videoPopupСontainer'}
|
containerName={'videoPopupСontainer'}
|
||||||
onResize={dispatchFit}
|
onResize={dispatchFit}
|
||||||
stickedScrollBars
|
stickedScrollBars
|
||||||
|
@ -84,7 +84,8 @@ import {
|
|||||||
RoomEvent,
|
RoomEvent,
|
||||||
type ScreenShareCaptureOptions,
|
type ScreenShareCaptureOptions,
|
||||||
Track,
|
Track,
|
||||||
type VideoCaptureOptions
|
type VideoCaptureOptions,
|
||||||
|
type Participant
|
||||||
} from 'livekit-client'
|
} from 'livekit-client'
|
||||||
import { get, writable } from 'svelte/store'
|
import { get, writable } from 'svelte/store'
|
||||||
|
|
||||||
@ -188,6 +189,8 @@ export const isShareWithSound = writable<boolean>(false)
|
|||||||
export const isMicAllowed = writable<boolean>(false)
|
export const isMicAllowed = writable<boolean>(false)
|
||||||
export const isCamAllowed = writable<boolean>(false)
|
export const isCamAllowed = writable<boolean>(false)
|
||||||
|
|
||||||
|
export const currentRoomAudioLevels = writable<Map<Ref<Person>, number>>(new Map())
|
||||||
|
|
||||||
function handleTrackSubscribed (
|
function handleTrackSubscribed (
|
||||||
track: RemoteTrack,
|
track: RemoteTrack,
|
||||||
publication: RemoteTrackPublication,
|
publication: RemoteTrackPublication,
|
||||||
@ -398,8 +401,13 @@ lk.on(RoomEvent.RoomMetadataChanged, (metadata) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
lk.on(RoomEvent.ActiveSpeakersChanged, (speakers: Participant[]) => {
|
||||||
|
currentRoomAudioLevels.set(new Map(speakers.map((it) => [it.identity as Ref<Person>, it.audioLevel])))
|
||||||
|
})
|
||||||
|
|
||||||
lk.on(RoomEvent.Connected, () => {
|
lk.on(RoomEvent.Connected, () => {
|
||||||
isConnected.set(true)
|
isConnected.set(true)
|
||||||
|
currentRoomAudioLevels.set(new Map())
|
||||||
sendMessage({ type: 'connect', value: true })
|
sendMessage({ type: 'connect', value: true })
|
||||||
isCurrentInstanceConnected.set(true)
|
isCurrentInstanceConnected.set(true)
|
||||||
isRecording.set(lk.isRecording)
|
isRecording.set(lk.isRecording)
|
||||||
@ -494,6 +502,7 @@ export async function disconnect (): Promise<void> {
|
|||||||
isMicEnabled.set(false)
|
isMicEnabled.set(false)
|
||||||
isCameraEnabled.set(false)
|
isCameraEnabled.set(false)
|
||||||
isSharingEnabled.set(false)
|
isSharingEnabled.set(false)
|
||||||
|
currentRoomAudioLevels.set(new Map())
|
||||||
sendMessage({ type: 'mic', value: false })
|
sendMessage({ type: 'mic', value: false })
|
||||||
sendMessage({ type: 'cam', value: false })
|
sendMessage({ type: 'cam', value: false })
|
||||||
sendMessage({ type: 'share', value: false })
|
sendMessage({ type: 'share', value: false })
|
||||||
|
Loading…
Reference in New Issue
Block a user