Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 62 additions & 63 deletions plugins/love-resources/src/components/Room.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,30 @@
import { ActionContext } from '@hcengineering/presentation'
import { Room as TypeRoom } from '@hcengineering/love'
import { getMetadata } from '@hcengineering/platform'
import { Label, Loading, deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
import { Label, Loading, Separator, defineSeparators, deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
import { onDestroy, onMount } from 'svelte'

import love from '../plugin'
import { waitForOfficeLoaded, currentRoom } from '../stores'
import { isFullScreen, lk } from '../utils'
import { isFullScreen } from '../utils'
import ControlBar from './meeting/ControlBar.svelte'
import ParticipantsListView from './meeting/ParticipantsListView.svelte'
import ScreenSharingView from './meeting/ScreenSharingView.svelte'

export let canMaximize: boolean = true
export let room: TypeRoom

let roomEl: HTMLDivElement
let roomElement: HTMLDivElement | undefined = undefined

let withScreenSharing: boolean = false
let loading: boolean = false
let configured: boolean = false

defineSeparators('love-room', [
{ minSize: 14, size: 'auto', maxSize: 'auto' },
{ minSize: 14, size: 18, maxSize: 75 }
])

onMount(async () => {
loading = true
const wsURL = getMetadata(love.metadata.WebSocketURL)
Expand All @@ -46,29 +51,21 @@

await waitForOfficeLoaded()

roomEl && roomEl.addEventListener('fullscreenchange', handleFullScreen)
roomElement?.addEventListener('fullscreenchange', handleFullScreen)
loading = false
})

let gridStyle = ''
let columns: number = 0
let rows: number = 0

onDestroy(() => {
roomEl.removeEventListener('fullscreenchange', handleFullScreen)
roomElement?.removeEventListener('fullscreenchange', handleFullScreen)
})

function updateStyle (count: number, screenSharing: boolean): void {
columns = screenSharing ? 1 : Math.min(Math.ceil(Math.sqrt(count)), 8)
rows = Math.ceil(count / columns)
gridStyle = `grid-template-columns: repeat(${columns}, 1fr); aspect-ratio: ${columns * 1280}/${rows * 720};`
const handleFullScreen = (): void => {
$isFullScreen = document.fullscreenElement != null
}

const handleFullScreen = () => ($isFullScreen = document.fullscreenElement != null)

function checkFullscreen (): void {
const needFullScreen = $isFullScreen
if (document.fullscreenElement && !needFullScreen) {
if (document.fullscreenElement != null && !needFullScreen) {
document
.exitFullscreen()
.then(() => {
Expand All @@ -78,8 +75,8 @@
console.log(`Error exiting fullscreen mode: ${err.message} (${err.name})`)
$isFullScreen = false
})
} else if (!document.fullscreenElement && needFullScreen && roomEl != null) {
roomEl
} else if (document.fullscreenElement == null && needFullScreen && roomElement != null) {
roomElement
.requestFullscreen()
.then(() => {
$isFullScreen = true
Expand All @@ -93,8 +90,8 @@

function onFullScreen (): void {
const needFullScreen = !$isFullScreen
if (!document.fullscreenElement && needFullScreen && roomEl != null) {
roomEl
if (document.fullscreenElement == null && needFullScreen && roomElement != null) {
roomElement
.requestFullscreen()
.then(() => {
$isFullScreen = true
Expand All @@ -116,11 +113,12 @@
}
}

$: if (((document.fullscreenElement && !$isFullScreen) || $isFullScreen) && roomEl) checkFullscreen()
$: updateStyle(lk.numParticipants, withScreenSharing)
$: if (((document.fullscreenElement != null && !$isFullScreen) || $isFullScreen) && roomElement !== undefined) {
checkFullscreen()
}
</script>

<div bind:this={roomEl} class="flex-col-center w-full h-full" class:theme-dark={$isFullScreen}>
<div bind:this={roomElement} class="flex-col-center w-full h-full" class:theme-dark={$isFullScreen}>
<ActionContext context={{ mode: 'workbench' }} />
{#if !configured}
<div class="flex justify-center error h-full w-full clear-mins">
Expand All @@ -132,20 +130,17 @@
<div
class="room-container"
class:sharing={withScreenSharing}
class:many={columns > 3}
class:hidden={loading}
class:mobile={$deviceInfo.isMobile}
>
<div class="screenContainer">
<ScreenSharingView bind:hasActiveTrack={withScreenSharing} />
</div>
<div class="videoGrid" style={withScreenSharing ? '' : gridStyle} class:scroll-m-0={withScreenSharing}>
<ParticipantsListView
room={room._id}
on:participantsCount={(evt) => {
updateStyle(evt.detail, withScreenSharing)
}}
/>
{#if withScreenSharing && !$deviceInfo.isMobile}
<Separator name={'love-room'} index={0} />
{/if}
<div class="participantsPane">
<ParticipantsListView room={room._id} />
</div>
</div>
{#if $currentRoom}
Expand All @@ -162,7 +157,6 @@
.room-container {
display: flex;
justify-content: center;
padding: 1rem;
width: 100%;
height: 100%;
min-width: 0;
Expand All @@ -173,6 +167,7 @@
display: flex;
justify-content: center;
align-items: center;
padding: 0.5rem;
max-height: 100%;
min-height: 0;
width: 100%;
Expand All @@ -190,55 +185,59 @@
&:not(.sharing) {
gap: 0;

.videoGrid {
display: grid;
grid-auto-rows: 1fr;
justify-content: center;
align-items: center;
gap: 1rem;
max-height: 100%;
max-width: 100%;
.participantsPane {
flex: 1;
--participants-gap: 1rem;
}
.screenContainer {
display: none;
}
}
&.sharing {
gap: 1rem;
gap: 0;

.videoGrid {
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 0.5rem;
margin: 0.5rem 0;
padding: 0 0.5rem;
width: 15rem;
min-width: 15rem;
min-height: 0;
max-width: 15rem;
.screenContainer {
flex: 1 1 auto;
min-width: 0;
}
}

&.many {
padding: 0.5rem;

&:not(.sharing) .videoGrid,
&.sharing {
gap: 0.5rem;
.participantsPane {
flex: 0 0 auto;
width: clamp(14rem, 22vw, 18rem);
max-width: clamp(14rem, 22vw, 18rem);
min-width: 12rem;
height: 100%;
overflow-y: auto;
--participants-gap: var(--spacing-0_5);
}
}

&.mobile {
padding: var(--spacing-0_5);

&:not(.sharing) .videoGrid,
&.sharing {
gap: var(--spacing-0_5);
.participantsPane {
padding: var(--spacing-0_25);
--participants-gap: var(--spacing-0_5);
}
}
}
.hidden {
display: none;
}

.participantsPane {
display: flex;
flex: 1 1 auto;
width: 100%;
height: 100%;
min-height: 0;
min-width: 0;
overflow: hidden;
padding: 0.5rem;
}

.participantsPane :global(.participants-grid) {
width: 100%;
height: 100%;
max-width: 100%;
}
</style>
69 changes: 29 additions & 40 deletions plugins/love-resources/src/components/VideoPopup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
<script lang="ts">
import { Ref } from '@hcengineering/core'
import { Room as TypeRoom } from '@hcengineering/love'
import { Scroller } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import { createEventDispatcher, afterUpdate } from 'svelte'

import ParticipantsListView from './meeting/ParticipantsListView.svelte'
import ScreenSharingView from './meeting/ScreenSharingView.svelte'
Expand All @@ -27,41 +26,31 @@
const dispatch = createEventDispatcher()

let withScreenSharing: boolean = false
let divScroll: HTMLElement
let participantsPane: HTMLElement | undefined

const dispatchFit = (_?: boolean): void => {
const dispatchFit = (): void => {
setTimeout(() => {
if (divScroll) {
const notFit: number = divScroll.scrollHeight - divScroll.clientHeight
dispatch('changeContent', { notFit })
}
if (participantsPane == null) return
const notFit = participantsPane.scrollHeight - participantsPane.clientHeight
dispatch('changeContent', { notFit })
}, 10)
}

$: dispatchFit(withScreenSharing)
afterUpdate(dispatchFit)
</script>

<div class="antiPopup videoPopup-container" class:isDock>
<div class="screenContainer" class:hidden={!withScreenSharing}>
<ScreenSharingView showLocalTrack={false} bind:hasActiveTrack={withScreenSharing} />
</div>
<Scroller
bind:divScroll
noStretch
padding={'.5rem'}
containerName={'videoPopupСontainer'}
onResize={dispatchFit}
stickedScrollBars
>
<div class="videoGrid">
<ParticipantsListView
{room}
on:participantsCount={(evt) => {
dispatchFit(evt.detail > 0)
}}
/>
</div>
</Scroller>
<div class="participantsPane" bind:this={participantsPane}>
<ParticipantsListView
{room}
on:participantsCount={() => {
dispatchFit()
}}
/>
</div>
<div class="antiNav-space" />
</div>

Expand Down Expand Up @@ -101,20 +90,20 @@
}
}

.videoGrid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-flow: row;
gap: var(--spacing-1);
}
@container videoPopupСontainer (max-width: 60rem) {
.videoGrid {
grid-template-columns: repeat(2, 1fr);
}
.participantsPane {
display: flex;
flex: 1 1 auto;
width: 100%;
height: 100%;
min-width: 0;
min-height: 0;
overflow: hidden;
padding: 0.5rem;
}
@container videoPopupСontainer (max-width: 30rem) {
.videoGrid {
grid-template-columns: 1fr;
}
.participantsPane :global(.participants-grid) {
width: 100%;
height: 100%;
max-width: 100%;
--participants-gap: var(--spacing-1);
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
@container (max-width: 440px) {
.bar[data-size='small'] .row {
justify-content: center;
gap: var(--g);
gap: 0.2rem;
}
.bar[data-size='small'] .left,
.bar[data-size='small'] .center,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
if (widget === undefined) return

if (!isMeetingWidgetCreated) {
createMeetingWidget(widget, room, meetingSessionConnected)
createMeetingWidget(widget, room)
}
} else {
if (isMeetingWidgetCreated) {
Expand Down
Loading
Loading