Added fullscreen mode (#5755)

Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
Alexander Platov 2024-06-07 18:30:34 +03:00 committed by GitHub
parent 5e9b9fbf70
commit 3f34143b16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 105 additions and 28 deletions

View File

@ -66,6 +66,18 @@
<path d="M10.6,16.6l3.6-3.6H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h13.2l-3.6-3.6L12,6l6,6l-6,6L10.6,16.6z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M12,2c-1.1,0-2,0.9-2,2v1c0,0.6-0.4,1-1,1S8,5.6,8,5V4c0-2.2,1.8-4,4-4h8c2.2,0,4,1.8,4,4v16c0,2.2-1.8,4-4,4 h-8c-2.2,0-4-1.8-4-4v-1c0-0.6,0.4-1,1-1s1,0.4,1,1v1c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V4c0-1.1-0.9-2-2-2H12z" />
</symbol>
<symbol id="fullscreen" viewBox="0 0 24 24">
<path d="M22,14.7c-0.5,0-1,0.4-1,1v4.2l-5.7-5.7c-0.4-0.4-1-0.4-1.3,0s-0.4,1,0,1.3l5.7,5.7h-4c-0.5,0-1,0.4-1,1s0.5,0.9,1,0.9H22c0.5,0,1-0.4,1-1v-6.4C23,15.2,22.6,14.7,22,14.7z" />
<path d="M4.2,2.8h4.2c0.5,0,1-0.4,1-1S8.8,1,8.3,1H2C1.4,1,1,1.4,1,2v6.4c0,0.5,0.4,1,1,1s0.9-0.5,0.9-1V4.2l5.7,5.7c0.4,0.4,1,0.4,1.3,0s0.4-1,0-1.3L4.2,2.8z" />
<path d="M22,1h-6.4c-0.5,0-1,0.4-1,1s0.4,1,1,1h4.2l-5.7,5.7c-0.4,0.4-0.4,1,0,1.3s1,0.4,1.3,0l5.7-5.7v4c0,0.5,0.4,1,1,1s0.9-0.5,0.9-1V2C23,1.4,22.6,1,22,1z" />
<path d="M8.6,14.1l-5.7,5.7v-4.2c0-0.5-0.4-1-1-1S1,15.2,1,15.7V22c0,0.6,0.4,1,1,1h6.4c0.5,0,1-0.4,1-1c0-0.6-0.5-0.9-1-0.9H4.2l5.7-5.7c0.4-0.4,0.4-1,0-1.3S8.9,13.7,8.6,14.1z" />
</symbol>
<symbol id="exitfullscreen" viewBox="0 0 24 24">
<path d="M16.9,15.6H21c0.5,0,1-0.4,1-1s-0.4-1-1-1h-6.3c-0.5,0-1,0.4-1,1v6.3c0,0.5,0.4,1,1,1c0.6,0,1-0.4,1-1v-4.1l5.7,5.7c0.4,0.4,1,0.4,1.3,0c0.4-0.4,0.4-1,0-1.3L16.9,15.6z" />
<path d="M9.3,2c-0.6,0-1,0.4-1,0.8V7L2.6,1.3c-0.4-0.4-1-0.4-1.3,0s-0.4,1,0,1.3L7,8.3H2.8C2.4,8.3,2,8.7,2,9.3s0.4,1,1,1h6.3c0.5,0,1-0.4,1-1V2.8C10.1,2.4,9.8,2,9.3,2z" />
<path d="M14.6,10.1h6.3c0.5,0,1-0.4,1-1c0-0.6-0.4-0.8-0.8-0.8h-4.1l5.7-5.7c0.4-0.4,0.4-1,0-1.3c-0.4-0.4-1-0.4-1.3,0L15.6,7V2.8c0-0.5-0.4-1-1-1s-1,0.4-1,1v6.3C13.8,9.8,14.1,10.1,14.6,10.1z" />
<path d="M9.3,13.8H2.8c-0.5,0-1,0.4-1,1c0,0.6,0.5,0.8,1,0.8H7l-5.7,5.7c-0.4,0.4-0.4,1,0,1.3c0.4,0.4,1,0.4,1.3,0l5.7-5.7V21c0,0.5,0.4,1,1,1s1-0.4,1-1v-6.3C10.1,14.1,9.8,13.8,9.3,13.8z" />
</symbol>
<symbol id="record" viewBox="0 0 256 256">
<path d="M128,24A104,104,0,1,0,232,128,104.11791,104.11791,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.09957,88.09957,0,0,1,128,216Zm72-88a72,72,0,1,1-72-72A72.08124,72.08124,0,0,1,200,128Z"/>
</symbol>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -55,6 +55,8 @@
"Record": "Record",
"StopRecord": "Stop record",
"LeaveRoomConfirmation": "Are you sure you want to leave the room?",
"ServiceNotConfigured": "Service is not configured"
"ServiceNotConfigured": "Service is not configured",
"FullscreenMode": "Full-screen mode",
"ExitingFullscreenMode": "Exiting fullscreen mode"
}
}

View File

@ -55,6 +55,8 @@
"Record": "Grabar",
"StopRecord": "Detener grabación",
"LeaveRoomConfirmation": "¿Estás seguro de que quieres salir de la sala?",
"ServiceNotConfigured": "El servicio no está configurado"
"ServiceNotConfigured": "El servicio no está configurado",
"FullscreenMode": "Modo de pantalla completa",
"ExitingFullscreenMode": "Salir del modo de pantalla completa"
}
}

View File

@ -55,6 +55,8 @@
"Record": "Gravar",
"StopRecord": "Parar gravação",
"LeaveRoomConfirmation": "Tem certeza de que deseja sair da sala?",
"ServiceNotConfigured": "O serviço não está configurado"
"ServiceNotConfigured": "O serviço não está configurado",
"FullscreenMode": "Modo de ecrã inteiro",
"ExitingFullscreenMode": "Saindo do modo de tela cheia"
}
}

View File

@ -55,6 +55,8 @@
"Record": "Запись",
"StopRecord": "Остановить запись",
"LeaveRoomConfirmation": "Вы уверены, что хотите покинуть комнату?",
"ServiceNotConfigured": "Сервис не настроен"
"ServiceNotConfigured": "Сервис не настроен",
"FullscreenMode": "Полноэкранный режим",
"ExitingFullscreenMode": "Выход из полноэкранного режима"
}
}

View File

@ -34,5 +34,7 @@ loadMetadata(love.icon, {
DND: `${icons}#dnd`,
Record: `${icons}#record`,
StopRecord: `${icons}#stopRecord`,
FullScreen: `${icons}#fullscreen`,
ExitFullScreen: `${icons}#exitfullscreen`,
Invite: `${icons}#invite`
})

View File

@ -20,8 +20,8 @@
import { copyTextToClipboard, getClient } from '@hcengineering/presentation'
import { IconUpOutline, ModernButton, SplitButton, eventToHTMLElement, showPopup } from '@hcengineering/ui'
import view from '@hcengineering/view'
import { Room, RoomType, isOffice, roomAccessIcon } from '@hcengineering/love'
import love from '../plugin'
import love, { Room, RoomType, isOffice, roomAccessIcon } from '@hcengineering/love'
import plugin from '../plugin'
import { currentRoom, myInfo, myOffice } from '../stores'
import {
isCameraEnabled,
@ -30,6 +30,7 @@
isRecording,
isRecordingAvailable,
isSharingEnabled,
isFullScreen,
leaveRoom,
record,
screenSharing,
@ -48,7 +49,7 @@
let allowLeave: boolean = false
$: allowCam = $currentRoom?.type === RoomType.Video
$: allowLeave = $myInfo?.room !== ($myOffice?._id ?? love.ids.Reception)
$: allowLeave = $myInfo?.room !== ($myOffice?._id ?? plugin.ids.Reception)
async function changeMute (): Promise<void> {
await setMic(!$isMicEnabled)
@ -97,15 +98,15 @@
const client = getClient()
const camKeys = client.getModel().findAllSync(view.class.Action, { _id: love.action.ToggleVideo })?.[0]?.keyBinding
const micKeys = client.getModel().findAllSync(view.class.Action, { _id: love.action.ToggleMic })?.[0]?.keyBinding
const camKeys = client.getModel().findAllSync(view.class.Action, { _id: plugin.action.ToggleVideo })?.[0]?.keyBinding
const micKeys = client.getModel().findAllSync(view.class.Action, { _id: plugin.action.ToggleMic })?.[0]?.keyBinding
</script>
<div class="bar w-full flex-center flex-gap-2 flex-no-shrink">
{#if room._id !== love.ids.Reception}
{#if room._id !== plugin.ids.Reception}
<ModernButton
icon={roomAccessIcon[room.access]}
tooltip={{ label: love.string.ChangeAccess }}
tooltip={{ label: plugin.string.ChangeAccess }}
kind={'secondary'}
size={'large'}
disabled={isOffice(room) && room.person !== me}
@ -115,8 +116,8 @@
{#if $isConnected}
<SplitButton
size={'large'}
icon={$isMicEnabled ? love.icon.MicEnabled : love.icon.MicDisabled}
showTooltip={{ label: $isMicEnabled ? love.string.Mute : love.string.UnMute, keys: micKeys }}
icon={$isMicEnabled ? plugin.icon.MicEnabled : plugin.icon.MicDisabled}
showTooltip={{ label: $isMicEnabled ? plugin.string.Mute : plugin.string.UnMute, keys: micKeys }}
action={changeMute}
secondIcon={IconUpOutline}
secondAction={micSettings}
@ -125,8 +126,8 @@
{#if allowCam}
<SplitButton
size={'large'}
icon={$isCameraEnabled ? love.icon.CamEnabled : love.icon.CamDisabled}
showTooltip={{ label: $isCameraEnabled ? love.string.StopVideo : love.string.StartVideo, keys: camKeys }}
icon={$isCameraEnabled ? plugin.icon.CamEnabled : plugin.icon.CamDisabled}
showTooltip={{ label: $isCameraEnabled ? plugin.string.StopVideo : plugin.string.StartVideo, keys: camKeys }}
disabled={!$isConnected}
action={changeCam}
secondIcon={IconUpOutline}
@ -136,8 +137,8 @@
{/if}
{#if allowShare}
<ModernButton
icon={$isSharingEnabled ? love.icon.SharingEnabled : love.icon.SharingDisabled}
tooltip={{ label: $isSharingEnabled ? love.string.StopShare : love.string.Share }}
icon={$isSharingEnabled ? plugin.icon.SharingEnabled : plugin.icon.SharingDisabled}
tooltip={{ label: $isSharingEnabled ? plugin.string.StopShare : plugin.string.Share }}
disabled={($screenSharing && !$isSharingEnabled) || !$isConnected}
kind={'secondary'}
size={'large'}
@ -146,8 +147,8 @@
{/if}
{#if hasAccountRole(getCurrentAccount(), AccountRole.User) && $isRecordingAvailable}
<ModernButton
icon={$isRecording ? love.icon.StopRecord : love.icon.Record}
tooltip={{ label: $isRecording ? love.string.StopRecord : love.string.Record }}
icon={$isRecording ? plugin.icon.StopRecord : plugin.icon.Record}
tooltip={{ label: $isRecording ? plugin.string.StopRecord : plugin.string.Record }}
disabled={!$isConnected}
kind={'secondary'}
size={'large'}
@ -156,10 +157,24 @@
{/if}
{/if}
<div class="bar__left-panel flex-gap-2 flex-center">
{#if $isConnected}
<ModernButton
icon={$isFullScreen ? love.icon.ExitFullScreen : love.icon.FullScreen}
tooltip={{
label: $isFullScreen ? plugin.string.ExitingFullscreenMode : plugin.string.FullscreenMode,
direction: 'top'
}}
kind={'secondary'}
size={'large'}
on:click={() => {
$isFullScreen = !$isFullScreen
}}
/>
{/if}
{#if hasAccountRole(getCurrentAccount(), AccountRole.User)}
<ModernButton
icon={view.icon.Copy}
tooltip={{ label: !linkCopied ? love.string.CopyGuestLink : view.string.Copied, direction: 'top' }}
tooltip={{ label: !linkCopied ? plugin.string.CopyGuestLink : view.string.Copied, direction: 'top' }}
kind={'secondary'}
size={'large'}
on:click={copyGuestLink}
@ -167,9 +182,9 @@
{/if}
{#if allowLeave}
<ModernButton
icon={love.icon.LeaveRoom}
label={love.string.LeaveRoom}
tooltip={{ label: love.string.LeaveRoom, direction: 'top' }}
icon={plugin.icon.LeaveRoom}
label={plugin.string.LeaveRoom}
tooltip={{ label: plugin.string.LeaveRoom, direction: 'top' }}
kind={'negative'}
size={'large'}
on:click={leave}

View File

@ -65,6 +65,7 @@
isCurrentInstanceConnected,
isMicEnabled,
isSharingEnabled,
isFullScreen,
leaveRoom,
screenSharing,
setCam,
@ -392,6 +393,13 @@
size={'small'}
action={changeShare}
/>
<ActionIcon
icon={$isFullScreen ? love.icon.ExitFullScreen : love.icon.FullScreen}
size={'small'}
action={() => {
$isFullScreen = !$isFullScreen
}}
/>
{/if}
{#if allowLeave}
<ActionIcon

View File

@ -17,7 +17,7 @@
import { personByIdStore } from '@hcengineering/contact-resources'
import { Room as TypeRoom } from '@hcengineering/love'
import { getMetadata } from '@hcengineering/platform'
import { Label, Loading, deviceOptionsStore as deviceInfo, resizeObserver } from '@hcengineering/ui'
import { Label, Loading, resizeObserver } from '@hcengineering/ui'
import {
LocalParticipant,
LocalTrackPublication,
@ -32,7 +32,15 @@
import { onDestroy, onMount, tick } from 'svelte'
import love from '../plugin'
import { currentRoom, infos, invites, myInfo, myRequests } from '../stores'
import { awaitConnect, isConnected, isCurrentInstanceConnected, lk, screenSharing, tryConnect } from '../utils'
import {
awaitConnect,
isConnected,
isCurrentInstanceConnected,
isFullScreen,
lk,
screenSharing,
tryConnect
} from '../utils'
import ControlBar from './ControlBar.svelte'
import ParticipantView from './ParticipantView.svelte'
@ -50,8 +58,7 @@
let participants: ParticipantData[] = []
const participantElements: ParticipantView[] = []
let screen: HTMLVideoElement
const remToPx = (rem: number): number => rem * $deviceInfo.fontSize
let roomEl: HTMLDivElement
function handleTrackSubscribed (
track: RemoteTrack,
@ -252,6 +259,7 @@
lk.on(RoomEvent.TrackUnsubscribed, handleTrackUnsubscribed)
lk.on(RoomEvent.LocalTrackPublished, handleLocalTrack)
lk.on(RoomEvent.LocalTrackUnpublished, handleLocalTrackUnsubscribed)
roomEl && roomEl.addEventListener('fullscreenchange', handleFullScreen)
loading = false
})
@ -290,6 +298,7 @@
lk.off(RoomEvent.TrackMuted, muteHandler)
lk.off(RoomEvent.TrackUnmuted, muteHandler)
lk.off(RoomEvent.LocalTrackUnpublished, handleLocalTrackUnsubscribed)
roomEl.removeEventListener('fullscreenchange', handleFullScreen)
})
function updateStyle (count: number, screenSharing: boolean): void {
@ -297,9 +306,27 @@
rows = Math.ceil(count / columns)
gridStyle = `grid-template-columns: repeat(${columns}, 1fr); aspect-ratio: ${columns * 1280}/${rows * 720};`
}
const handleFullScreen = () => ($isFullScreen = document.fullscreenElement != null)
function toggleFullscreen () {
if (!document.fullscreenElement) {
roomEl
.requestFullscreen()
.then(() => ($isFullScreen = true))
.catch((err) => {
console.log(`Error attempting to enable fullscreen mode: ${err.message} (${err.name})`)
$isFullScreen = false
})
} else {
document.exitFullscreen()
$isFullScreen = false
}
}
$: if (((document.fullscreenElement && !$isFullScreen) || $isFullScreen) && roomEl) toggleFullscreen()
</script>
<div class="flex-col-center w-full h-full">
<div bind:this={roomEl} class="flex-col-center w-full h-full" class:theme-dark={$isFullScreen}>
{#if $isConnected && !$isCurrentInstanceConnected}
<div class="flex justify-center error h-full w-full clear-mins">
<Label label={love.string.AnotherWindowError} />

View File

@ -67,6 +67,8 @@ export default mergeIds(loveId, love, {
Record: '' as IntlString,
StopRecord: '' as IntlString,
ServiceNotConfigured: '' as IntlString,
FullscreenMode: '' as IntlString,
ExitingFullscreenMode: '' as IntlString,
Invite: '' as IntlString,
KnockAction: '' as IntlString
}

View File

@ -116,6 +116,7 @@ export const isRecordingAvailable = writable<boolean | undefined>(undefined)
export const isMicEnabled = writable<boolean>(false)
export const isCameraEnabled = writable<boolean>(false)
export const isSharingEnabled = writable<boolean>(false)
export const isFullScreen = writable<boolean>(false)
function handleTrackSubscribed (
track: RemoteTrack,

View File

@ -135,6 +135,8 @@ const love = plugin(loveId, {
DND: '' as Asset,
Record: '' as Asset,
StopRecord: '' as Asset,
FullScreen: '' as Asset,
ExitFullScreen: '' as Asset,
Invite: '' as Asset
},
metadata: {