platform/plugins/love-resources/src/components/RoomPopup.svelte
Alexander Platov 8b44249cec
Minor UI fixes (#6171)
Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
2024-07-29 22:03:28 +07:00

287 lines
8.1 KiB
Svelte

<!--
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { Person, PersonAccount } from '@hcengineering/contact'
import { personByIdStore, UserInfo } from '@hcengineering/contact-resources'
import { IdMap, getCurrentAccount } from '@hcengineering/core'
import ui, {
ModernButton,
SplitButton,
IconArrowLeft,
IconUpOutline,
Label,
eventToHTMLElement,
getCurrentLocation,
location,
navigate,
showPopup,
Scroller,
closePanel
} from '@hcengineering/ui'
import {
ParticipantInfo,
Room,
RoomType,
isOffice,
loveId,
roomAccessIcon,
roomAccessLabel
} from '@hcengineering/love'
import { createEventDispatcher } from 'svelte'
import love from '../plugin'
import { currentRoom, infos, invites, myInfo, myOffice, myRequests } from '../stores'
import {
getRoomName,
isCameraEnabled,
isConnected,
isMicEnabled,
isSharingEnabled,
leaveRoom,
screenSharing,
setCam,
setMic,
setShare,
tryConnect
} from '../utils'
import CamSettingPopup from './CamSettingPopup.svelte'
import MicSettingPopup from './MicSettingPopup.svelte'
import RoomAccessPopup from './RoomAccessPopup.svelte'
export let room: Room
function getPerson (info: ParticipantInfo | undefined, employees: IdMap<Person>): Person | undefined {
if (info !== undefined) {
return employees.get(info.person)
}
}
let joined: boolean = false
$: joined = $myInfo?.room === room._id
$: allowLeave = $myInfo?.room !== ($myOffice?._id ?? love.ids.Reception)
let info: ParticipantInfo[] = []
$: info = $infos.filter((p) => p.room === room._id)
let allowCam: boolean = false
const allowShare: boolean = true
$: allowCam = $currentRoom?.type === RoomType.Video
const dispatch = createEventDispatcher()
async function changeMute (): Promise<void> {
await setMic(!$isMicEnabled)
}
async function changeCam (): Promise<void> {
await setCam(!$isCameraEnabled)
}
async function changeShare (): Promise<void> {
await setShare(!$isSharingEnabled)
}
async function leave (): Promise<void> {
await leaveRoom($myInfo, $myOffice)
dispatch('close')
}
async function connect (): Promise<void> {
await tryConnect($personByIdStore, $myInfo, room, info, $myRequests, $invites)
dispatch('close')
}
function back (): void {
closePanel()
const loc = getCurrentLocation()
loc.path[2] = loveId
loc.path.length = 3
navigate(loc)
}
function micSettings (e: MouseEvent): void {
showPopup(MicSettingPopup, {}, eventToHTMLElement(e))
}
function camSettings (e: MouseEvent): void {
showPopup(CamSettingPopup, {}, eventToHTMLElement(e))
}
function setAccess (e: MouseEvent): void {
showPopup(RoomAccessPopup, { room }, eventToHTMLElement(e), (res) => {
if (res !== undefined) {
room.access = res
}
})
}
const me = (getCurrentAccount() as PersonAccount).person
$: myRoom = isOffice(room) && room.person === me
</script>
<div class="antiPopup room-popup">
<div class="room-label"><Label label={love.string.Room} /></div>
<div class="title overflow-label">
{getRoomName(room, $personByIdStore)}
</div>
<div class="room-popup__content">
<Scroller padding={'0.5rem'} stickedScrollBars>
<div class="room-popup__content-grid">
{#each info as inf}
{@const person = getPerson(inf, $personByIdStore)}
{#if person}
<div class="person"><UserInfo value={person} size={'medium'} showStatus={false} /></div>
{/if}
{/each}
</div>
</Scroller>
</div>
{#if joined && $isConnected}
<div class="room-btns" class:no-video={!allowCam}>
<SplitButton
size={'large'}
icon={$isMicEnabled ? love.icon.MicEnabled : love.icon.MicDisabled}
label={$isMicEnabled ? love.string.Mute : love.string.UnMute}
showTooltip={{ label: $isMicEnabled ? love.string.Mute : love.string.UnMute }}
action={changeMute}
secondIcon={IconUpOutline}
secondAction={micSettings}
separate
/>
{#if allowCam}
<SplitButton
size={'large'}
icon={$isCameraEnabled ? love.icon.CamEnabled : love.icon.CamDisabled}
label={$isCameraEnabled ? love.string.StopVideo : love.string.StartVideo}
showTooltip={{ label: $isCameraEnabled ? love.string.StopVideo : love.string.StartVideo }}
disabled={!$isConnected}
action={changeCam}
secondIcon={IconUpOutline}
secondAction={camSettings}
separate
/>
{/if}
{#if allowShare}
<ModernButton
icon={$isSharingEnabled ? love.icon.SharingEnabled : love.icon.SharingDisabled}
label={$isSharingEnabled ? love.string.StopShare : love.string.Share}
tooltip={{ label: $isSharingEnabled ? love.string.StopShare : love.string.Share }}
disabled={($screenSharing && !$isSharingEnabled) || !$isConnected}
kind={'secondary'}
size={'large'}
on:click={changeShare}
/>
{/if}
<ModernButton
icon={roomAccessIcon[room.access]}
label={roomAccessLabel[room.access]}
tooltip={{ label: love.string.ChangeAccess }}
kind={'secondary'}
size={'large'}
disabled={isOffice(room) && room.person !== me}
on:click={setAccess}
/>
</div>
{/if}
{#if (joined && !myRoom) || (!allowLeave && $myRequests.length === 0 && !myRoom)}
<div class="btns flex-row-center flex-reverse flex-no-shrink w-full flex-gap-2">
{#if allowLeave}
<ModernButton
label={love.string.LeaveRoom}
icon={love.icon.LeaveRoom}
size={'large'}
kind={'negative'}
on:click={leave}
/>
{:else if $myRequests.length === 0 && !myRoom}
<ModernButton
icon={love.icon.EnterRoom}
label={love.string.EnterRoom}
size={'large'}
kind={'primary'}
autoFocus
on:click={connect}
/>
{/if}
{#if $location.path[2] !== loveId}
<ModernButton icon={IconArrowLeft} label={ui.string.Back} kind={'secondary'} size={'large'} on:click={back} />
{/if}
</div>
{/if}
</div>
<style lang="scss">
.room-popup {
padding: var(--spacing-2);
min-width: 35rem;
max-width: 46rem;
max-height: 40rem;
.room-label {
margin-top: var(--spacing-0_5);
text-transform: uppercase;
}
.title {
flex-shrink: 0;
margin-bottom: var(--spacing-2);
font-size: 1.5rem;
color: var(--theme-caption-color);
}
.room-popup__content {
display: flex;
flex-direction: column;
min-height: 0;
min-width: 0;
border: 1px solid var(--theme-popup-divider);
border-radius: var(--medium-BorderRadius);
&-grid {
display: grid;
grid-template-columns: 1fr 1fr;
justify-content: stretch;
align-items: center;
gap: var(--spacing-1) var(--spacing-2);
.person {
display: flex;
align-items: center;
min-width: 0;
min-height: 0;
color: var(--theme-content-color);
}
}
}
.room-btns {
display: flex;
justify-content: center;
align-items: center;
padding: var(--spacing-1) 0 var(--spacing-0_5);
gap: var(--spacing-1);
min-width: 0;
min-height: 0;
& + .btns {
padding-top: var(--spacing-1_5);
}
}
.btns {
padding-top: var(--spacing-2);
}
}
</style>