Improve office click handler (#5751)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2024-06-07 15:29:30 +05:00 committed by GitHub
parent 7433a23728
commit e2f48dc7ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 155 additions and 36 deletions

View File

@ -30,6 +30,9 @@
}
.floorGrid-room {
&.hovered:hover {
z-index: 10;
}
&__header {
align-items: center;
top: calc(100% / var(--huly-floor-roomHeight) / 3 * -1.6 + 0.375rem + 1px);

View File

@ -72,4 +72,9 @@
<symbol id="stopRecord" 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" fill="#FF6711"/>
</symbol>
<symbol id="invite" viewBox="0 0 32 32">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 18C20.4183 18 24 14.4183 24 10C24 5.58172 20.4183 2 16 2C11.5817 2 8 5.58172 8 10C8 14.4183 11.5817 18 16 18ZM16 16C19.3137 16 22 13.3137 22 10C22 6.68629 19.3137 4 16 4C12.6863 4 10 6.68629 10 10C10 13.3137 12.6863 16 16 16Z" />
<path d="M24 21C24 20.4477 24.4477 20 25 20C25.5523 20 26 20.4477 26 21V24H29C29.5523 24 30 24.4477 30 25C30 25.5523 29.5523 26 29 26H26V29C26 29.5523 25.5523 30 25 30C24.4477 30 24 29.5523 24 29V26H21C20.4477 26 20 25.5523 20 25C20 24.4477 20.4477 24 21 24H24V21Z" />
<path d="M13 20C9.13401 20 6 23.134 6 27V29C6 29.5523 6.44772 30 7 30C7.55228 30 8 29.5523 8 29V27C8 24.2386 10.2386 22 13 22H17C17.5523 22 18 21.5523 18 21C18 20.4477 17.5523 20 17 20H13Z" />
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -44,6 +44,8 @@
"NoiseCancellation": "Noise cancellation",
"KnockingLabel": "Knocking",
"InivitingLabel": "Invite",
"Invite": "Invite",
"KnockAction": "Knock",
"NoiseCancellationNotSupported": "Noise cancellation is not supported in this browser",
"Blur": "Background blur",
"BlurRadius": "Radius",

View File

@ -43,7 +43,9 @@
"YouInivite": "Estás invitando a unirte",
"NoiseCancellation": "Cancelación de ruido",
"KnockingLabel": "Tocando",
"InivitingLabel": "Invitar",
"InivitingLabel": "Invitación",
"Invite": "Invitar",
"KnockAction": "Golpear",
"NoiseCancellationNotSupported": "La cancelación de ruido no es compatible con tu navegador",
"Blur": "Desenfoque de fondo",
"BlurRadius": "Radio de desenfoque",

View File

@ -43,7 +43,9 @@
"YouInivite": "Você está convidando para entrar",
"NoiseCancellation": "Cancelamento de ruído",
"KnockingLabel": "Batendo",
"InivitingLabel": "Convidar",
"InivitingLabel": "Convite",
"Invite": "Convidar",
"KnockAction": "Bater",
"NoiseCancellationNotSupported": "Seu navegador não suporta cancelamento de ruído",
"Blur": "Desfoque de fundo",
"BlurRadius": "Raio de desfoque",

View File

@ -39,6 +39,8 @@
"RenameAFloor": "Переименовать этаж",
"StartWithoutVideo": "Всегда начинать с выключенной камерой",
"StartWithMutedMic": "Всегда начинать с выключенным звуком",
"Invite": "Пригласить",
"KnockAction": "Постучать",
"InvitingYou": "{name} приглашает вас присоединиться",
"YouInivite": "Вы приглашаете присоединиться",
"NoiseCancellation": "Подавление шума",

View File

@ -33,5 +33,6 @@ loadMetadata(love.icon, {
Knock: `${icons}#knock`,
DND: `${icons}#dnd`,
Record: `${icons}#record`,
StopRecord: `${icons}#stopRecord`
StopRecord: `${icons}#stopRecord`,
Invite: `${icons}#invite`
})

View File

@ -16,6 +16,18 @@
import { PersonAccount, formatName } from '@hcengineering/contact'
import { Avatar, personByIdStore } from '@hcengineering/contact-resources'
import { IdMap, Ref, getCurrentAccount, toIdMap } from '@hcengineering/core'
import {
Floor,
Invite,
JoinRequest,
Office,
ParticipantInfo,
RequestStatus,
Room,
RoomType,
isOffice,
loveId
} from '@hcengineering/love'
import { getEmbeddedLabel } from '@hcengineering/platform'
import { MessageBox, createQuery, getClient } from '@hcengineering/presentation'
import {
@ -30,18 +42,6 @@
tooltip
} from '@hcengineering/ui'
import view from '@hcengineering/view'
import {
Floor,
Invite,
JoinRequest,
Office,
ParticipantInfo,
RequestStatus,
Room,
RoomType,
isOffice,
loveId
} from '@hcengineering/love'
import { onDestroy } from 'svelte'
import love from '../plugin'
import {
@ -60,7 +60,6 @@
connectRoom,
disconnect,
getRoomName,
invite,
isCameraEnabled,
isConnected,
isCurrentInstanceConnected,
@ -77,6 +76,7 @@
import FloorPopup from './FloorPopup.svelte'
import InvitePopup from './InvitePopup.svelte'
import MicSettingPopup from './MicSettingPopup.svelte'
import PersonActionPopup from './PersonActionPopup.svelte'
import RequestPopup from './RequestPopup.svelte'
import RequestingPopup from './RequestingPopup.svelte'
import RoomPopup from './RoomPopup.svelte'
@ -338,6 +338,18 @@
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
function participantClickHandler (e: MouseEvent, participant: ParticipantInfo): void {
if ($myInfo !== undefined) {
showPopup(PersonActionPopup, { room: reception, person: participant.person }, eventToHTMLElement(e))
}
}
function getParticipantClickHandler (participant: ParticipantInfo): (e: MouseEvent) => void {
return (e: MouseEvent) => {
participantClickHandler(e, participant)
}
}
</script>
<div class="flex-row-center flex-gap-2">
@ -422,11 +434,7 @@
{#each receptionParticipants as participant (participant._id)}
<div
use:tooltip={{ label: getEmbeddedLabel(formatName(participant.name)) }}
on:click={() => {
if (myInfo) {
invite(participant.person, $myInfo?.room)
}
}}
on:click={getParticipantClickHandler(participant)}
>
<Avatar name={participant.name} size={'card'} person={$personByIdStore.get(participant.person)} />
</div>

View File

@ -0,0 +1,45 @@
<script lang="ts">
import { Person } from '@hcengineering/contact'
import { Ref } from '@hcengineering/core'
import { Room, RoomAccess } from '@hcengineering/love'
import { ActionIcon } from '@hcengineering/ui'
import love from '../plugin'
import { invite, tryConnect } from '../utils'
import { infos, invites, myInfo, myRequests } from '../stores'
import { personByIdStore } from '@hcengineering/contact-resources'
export let room: Room
export let person: Ref<Person>
$: info = $infos.filter((p) => p.room === room._id)
</script>
<div class="p-3 flex-gap-2 antiPopup">
{#if $myInfo?.room !== room._id}
<ActionIcon
size={'small'}
label={love.string.Invite}
icon={love.icon.Invite}
action={() => {
invite(person, $myInfo?.room)
}}
/>
{#if room.access === RoomAccess.Knock}
<ActionIcon
size={'small'}
label={love.string.KnockAction}
icon={love.icon.Knock}
action={() => {
tryConnect($personByIdStore, $myInfo, room, info, $myRequests, $invites)
}}
/>
{/if}
{/if}
</div>
<style lang="scss">
.antiPopup {
flex-direction: row;
margin-top: -0.75rem;
}
</style>

View File

@ -16,12 +16,13 @@
import { Person, type PersonAccount } from '@hcengineering/contact'
import { Avatar, personByIdStore } from '@hcengineering/contact-resources'
import { IdMap, getCurrentAccount } from '@hcengineering/core'
import { Icon, Label } from '@hcengineering/ui'
import { ParticipantInfo, Room, RoomAccess, RoomType } from '@hcengineering/love'
import { Icon, Label, eventToHTMLElement, showPopup, showTooltip } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import love from '../plugin'
import { invites, myInfo, myRequests } from '../stores'
import { getRoomLabel, invite, tryConnect } from '../utils'
import { createEventDispatcher } from 'svelte'
import { getRoomLabel, tryConnect } from '../utils'
import PersonActionPopup from './PersonActionPopup.svelte'
export let room: Room
export let info: ParticipantInfo[]
@ -51,17 +52,60 @@
}
function mouseEnter (): void {
hovered = true
dispatch('hover', { name: getRoomLabel(room, $personByIdStore) })
}
function clickHandler (x: number, y: number, person: Person | undefined): void {
function mouseLeave (): void {
hovered = false
}
function clickHandler (e: MouseEvent, x: number, y: number, person: Person | undefined): void {
if (person !== undefined) {
if (room._id === $myInfo?.room) return
invite(person._id, $myInfo?.room)
if (room._id === $myInfo?.room || $myInfo === undefined) return
showPopup(PersonActionPopup, { room, person: person._id }, eventToHTMLElement(e))
} else {
tryConnect($personByIdStore, $myInfo, room, info, $myRequests, $invites, { x, y })
}
}
$: extraRow = calcExtraRows(hovered, room, info, $myInfo)
function calcExtraRows (
hovered: boolean,
room: Room,
info: ParticipantInfo[],
myInfo: ParticipantInfo | undefined
): number {
if (!hovered) return 0
let maxX = info.reduce((acc, p) => {
acc = Math.max(acc, p.x)
return acc
}, 0)
maxX++
let init = maxX > room.width ? maxX - room.width : 0
for (let y = 0; y < room.height; y++) {
for (let x = 0; x < room.width; x++) {
if (info.find((p) => p.x === x && p.y === y) === undefined) {
return init
}
}
}
if (myInfo?.room !== room._id) {
init++
while (init < 5) {
const x = room.width + init
for (let y = 0; y < room.height; y++) {
if (info.find((p) => p.x === x && p.y === y) === undefined) {
return init
}
}
init++
}
}
return init
}
</script>
<!-- svelte-ignore a11y-no-static-element-interactions -->
@ -73,17 +117,19 @@
class:hovered
class:disabled
class:myOffice={$myInfo?.room === room._id}
style:--huly-floor-roomWidth={room.width}
style:--huly-floor-roomWidth={room.width + extraRow}
style:--huly-floor-roomHeight={room.height}
style:grid-column={`${room.x + 2} / span ${room.width}`}
style:grid-column={`${room.x + 2} / span ${room.width + extraRow}`}
style:grid-row={`${room.y + 2} / span ${room.height}`}
style:grid-template-columns={`repeat(${room.width}, 1fr)`}
style:grid-template-columns={`repeat(${room.width + extraRow}, 1fr)`}
style:grid-template-rows={`repeat(${room.height}, 1fr)`}
style:aspect-ratio={`${room.width} / ${room.height}`}
style:aspect-ratio={`${room.width + extraRow} / ${room.height}`}
on:mouseover|stopPropagation
on:mouseenter|stopPropagation={mouseEnter}
on:mouseleave|stopPropagation={mouseLeave}
>
{#each new Array(room.height) as _, y}
{#each new Array(room.width) as _, x}
{#each new Array(room.width + extraRow) as _, x}
{@const personInfo = getPersonInfo(y, x, info)}
{@const person = getPerson(personInfo, $personByIdStore)}
<!-- svelte-ignore a11y-click-events-have-key-events -->
@ -101,8 +147,8 @@
hoveredRoomX = undefined
hoveredRoomY = undefined
}}
on:click={() => {
clickHandler(x, y, person)
on:click={(e) => {
clickHandler(e, x, y, person)
}}
>
{#if personInfo}

View File

@ -66,6 +66,8 @@ export default mergeIds(loveId, love, {
CopyGuestLink: '' as IntlString,
Record: '' as IntlString,
StopRecord: '' as IntlString,
ServiceNotConfigured: '' as IntlString
ServiceNotConfigured: '' as IntlString,
Invite: '' as IntlString,
KnockAction: '' as IntlString
}
})

View File

@ -134,7 +134,8 @@ const love = plugin(loveId, {
Knock: '' as Asset,
DND: '' as Asset,
Record: '' as Asset,
StopRecord: '' as Asset
StopRecord: '' as Asset,
Invite: '' as Asset
},
metadata: {
WebSocketURL: '' as Metadata<string>,