Meeting fixes (#7218)
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 / docker-build (push) Blocked by required conditions
CI / dist-build (push) Blocked by required conditions

1

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina 2024-11-21 22:34:31 +04:00 committed by GitHub
parent 500a221ceb
commit 1b415d6a6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 87 additions and 36 deletions

View File

@ -45,8 +45,10 @@
dispatch('open', { ignoreKeys: ['name'] }) dispatch('open', { ignoreKeys: ['name'] })
}) })
let tryConnecting = false
async function connect (): Promise<void> { async function connect (): Promise<void> {
connecting = true tryConnecting = true
const place = $selectedRoomPlace const place = $selectedRoomPlace
await tryConnect( await tryConnect(
$personByIdStore, $personByIdStore,
@ -57,11 +59,11 @@
$invites, $invites,
place?._id === object._id ? { x: place.x, y: place.y } : undefined place?._id === object._id ? { x: place.x, y: place.y } : undefined
) )
connecting = false tryConnecting = false
selectedRoomPlace.set(undefined) selectedRoomPlace.set(undefined)
} }
$: connecting = connecting || ($currentRoom?._id === object._id && !$isConnected) $: connecting = tryConnecting || ($currentRoom?._id === object._id && !$isConnected)
let connectLabel: IntlString = $infos.some(({ room }) => room === object._id) let connectLabel: IntlString = $infos.some(({ room }) => room === object._id)
? love.string.JoinMeeting ? love.string.JoinMeeting
@ -72,6 +74,17 @@
} else if (!connecting) { } else if (!connecting) {
connectLabel = love.string.StartMeeting connectLabel = love.string.StartMeeting
} }
function showConnectionButton (object: Room, isConnected: boolean, myOffice?: Room, currentRoom?: Room): boolean {
// Do not show connect button in my office
if (object._id === myOffice?._id) return false
// Show during connecting with spinner
if (connecting) return true
// Do not show connect button if we are already connected to the room
if (isConnected && currentRoom?._id === object._id) return false
return true
}
</script> </script>
<div class="flex-row-stretch"> <div class="flex-row-stretch">
@ -85,7 +98,7 @@
focusIndex={1} focusIndex={1}
/> />
</div> </div>
{#if object._id !== $myOffice?._id && ($currentRoom?._id !== object._id || connecting)} {#if showConnectionButton(object, $isConnected, $myOffice, $currentRoom)}
<ModernButton label={connectLabel} size="large" kind={'primary'} on:click={connect} loading={connecting} /> <ModernButton label={connectLabel} size="large" kind={'primary'} on:click={connect} loading={connecting} />
{/if} {/if}
</div> </div>

View File

@ -16,16 +16,15 @@
import { Person, type PersonAccount } from '@hcengineering/contact' import { Person, type PersonAccount } from '@hcengineering/contact'
import { Avatar, personByIdStore } from '@hcengineering/contact-resources' import { Avatar, personByIdStore } from '@hcengineering/contact-resources'
import { IdMap, getCurrentAccount } from '@hcengineering/core' import { IdMap, getCurrentAccount } from '@hcengineering/core'
import { isOffice, ParticipantInfo, Room, RoomAccess, RoomType } from '@hcengineering/love' import { isOffice, ParticipantInfo, Room, RoomAccess, RoomType, MeetingStatus } from '@hcengineering/love'
import { Icon, Label, eventToHTMLElement, showPopup } from '@hcengineering/ui' import { Icon, Label, eventToHTMLElement, showPopup } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import { getClient } from '@hcengineering/presentation' import { getClient } from '@hcengineering/presentation'
import { openDoc } from '@hcengineering/view-resources' import { openDoc } from '@hcengineering/view-resources'
import { get } from 'svelte/store'
import love from '../plugin' import love from '../plugin'
import { myInfo, selectedRoomPlace, currentRoom, currentMeetingMinutes } from '../stores' import { myInfo, selectedRoomPlace, currentRoom, currentMeetingMinutes } from '../stores'
import { getRoomLabel, lk } from '../utils' import { getRoomLabel, lk, isConnected } from '../utils'
import PersonActionPopup from './PersonActionPopup.svelte' import PersonActionPopup from './PersonActionPopup.svelte'
import RoomLanguage from './RoomLanguage.svelte' import RoomLanguage from './RoomLanguage.svelte'
@ -67,14 +66,20 @@
async function openRoom (x: number, y: number): Promise<void> { async function openRoom (x: number, y: number): Promise<void> {
const client = getClient() const client = getClient()
const hierarchy = client.getHierarchy() const hierarchy = client.getHierarchy()
if ($currentRoom?._id === room._id) { if ($isConnected && $currentRoom?._id === room._id) {
const sid = await lk.getSid() const sid = await lk.getSid()
const meetingMinutes = let meeting = $currentMeetingMinutes
get(currentMeetingMinutes) ?? (await client.findOne(love.class.MeetingMinutes, { sid, attachedTo: room._id })) if (meeting?.sid !== sid || meeting?.attachedTo !== room._id || meeting?.status !== MeetingStatus.Active) {
if (meetingMinutes === undefined) { meeting = await client.findOne(love.class.MeetingMinutes, {
sid,
attachedTo: room._id,
status: MeetingStatus.Active
})
}
if (meeting === undefined) {
await openDoc(hierarchy, room) await openDoc(hierarchy, room)
} else { } else {
await openDoc(hierarchy, meetingMinutes) await openDoc(hierarchy, meeting)
} }
} else { } else {
selectedRoomPlace.set({ _id: room._id, x, y }) selectedRoomPlace.set({ _id: room._id, x, y })

View File

@ -15,13 +15,13 @@
<script lang="ts"> <script lang="ts">
import { closeWidget, minimizeSidebar, WidgetState } from '@hcengineering/workbench-resources' import { closeWidget, minimizeSidebar, WidgetState } from '@hcengineering/workbench-resources'
import { createQuery } from '@hcengineering/presentation' import { createQuery } from '@hcengineering/presentation'
import { MeetingMinutes, Room } from '@hcengineering/love' import { MeetingMinutes, MeetingStatus, Room } from '@hcengineering/love'
import { Loading } from '@hcengineering/ui' import { Loading } from '@hcengineering/ui'
import love from '../../plugin' import love from '../../plugin'
import VideoTab from './VideoTab.svelte' import VideoTab from './VideoTab.svelte'
import { isCurrentInstanceConnected, lk } from '../../utils' import { isCurrentInstanceConnected, lk } from '../../utils'
import { currentRoom, currentMeetingMinutes } from '../../stores' import { currentMeetingMinutes, currentRoom } from '../../stores'
import ChatTab from './ChatTab.svelte' import ChatTab from './ChatTab.svelte'
import TranscriptionTab from './TranscriptionTab.svelte' import TranscriptionTab from './TranscriptionTab.svelte'
@ -58,13 +58,17 @@
} }
$: if (sid != null && room !== undefined) { $: if (sid != null && room !== undefined) {
meetingQuery.query(love.class.MeetingMinutes, { sid, attachedTo: room._id }, async (res) => { meetingQuery.query(
meetingMinutes = res[0] love.class.MeetingMinutes,
if (meetingMinutes) { { sid, attachedTo: room._id, status: MeetingStatus.Active },
currentMeetingMinutes.set(meetingMinutes) async (res) => {
meetingMinutes = res[0]
if (meetingMinutes) {
currentMeetingMinutes.set(meetingMinutes)
}
isMeetingMinutesLoaded = true
} }
isMeetingMinutesLoaded = true )
})
} else { } else {
meetingQuery.unsubscribe() meetingQuery.unsubscribe()
meetingMinutes = undefined meetingMinutes = undefined

View File

@ -85,7 +85,7 @@ import { getObjectLinkFragment } from '@hcengineering/view-resources'
import { sendMessage } from './broadcast' import { sendMessage } from './broadcast'
import love from './plugin' import love from './plugin'
import { $myPreferences, currentRoom, currentMeetingMinutes, selectedRoomPlace } from './stores' import { $myPreferences, currentRoom, currentMeetingMinutes, selectedRoomPlace, myOffice } from './stores'
import RoomSettingsPopup from './components/RoomSettingsPopup.svelte' import RoomSettingsPopup from './components/RoomSettingsPopup.svelte'
export const selectedCamId = 'selectedDevice_cam' export const selectedCamId = 'selectedDevice_cam'
@ -427,18 +427,32 @@ function initRoomMetadata (metadata: string | undefined): void {
void record(room) void record(room)
} }
} }
export async function connect (name: string, room: Room, _id: string): Promise<void> {
async function withRetries (fn: () => Promise<void>, retries: number, delay: number): Promise<void> {
for (let attempt = 0; attempt < retries; attempt++) {
try {
await fn()
return
} catch (error) {
if (attempt >= retries) {
throw error
}
console.error(error)
console.log(`Attempt ${attempt} failed. Retrying in ${delay}ms...`)
await new Promise((resolve) => setTimeout(resolve, delay))
}
}
}
async function connect (name: string, room: Room, _id: string): Promise<void> {
const wsURL = getMetadata(love.metadata.WebSocketURL) const wsURL = getMetadata(love.metadata.WebSocketURL)
if (wsURL === undefined) { if (wsURL === undefined) {
return return
} }
try {
const token = await getToken(room.name, room._id, _id, name) const token = await getToken(room.name, room._id, _id, name)
await lk.connect(wsURL, token) await lk.connect(wsURL, token)
sendMessage({ type: 'connect', value: true }) sendMessage({ type: 'connect', value: true })
} catch (err) {
console.error(err)
}
} }
export async function awaitConnect (): Promise<void> { export async function awaitConnect (): Promise<void> {
@ -647,7 +661,11 @@ async function navigateToOfficeDoc (hierarchy: Hierarchy, object: Doc): Promise<
async function openMeetingMinutes (room: Room): Promise<void> { async function openMeetingMinutes (room: Room): Promise<void> {
const client = getClient() const client = getClient()
const sid = await lk.getSid() const sid = await lk.getSid()
const doc = await client.findOne(love.class.MeetingMinutes, { sid }) const doc = await client.findOne(love.class.MeetingMinutes, {
sid,
attachedTo: room._id,
status: MeetingStatus.Active
})
if (doc === undefined) { if (doc === undefined) {
const date = new Date() const date = new Date()
@ -696,9 +714,6 @@ async function openMeetingMinutes (room: Room): Promise<void> {
if (loc.path[2] === loveId || room.type === RoomType.Video) { if (loc.path[2] === loveId || room.type === RoomType.Video) {
await navigateToOfficeDoc(client.getHierarchy(), doc) await navigateToOfficeDoc(client.getHierarchy(), doc)
} }
if (doc.status !== MeetingStatus.Active) {
void client.update(doc, { status: MeetingStatus.Active, meetingEnd: undefined })
}
} }
} }
@ -711,9 +726,20 @@ export async function connectRoom (
): Promise<void> { ): Promise<void> {
await disconnect() await disconnect()
await moveToRoom(x, y, currentInfo, currentPerson, room, getMetadata(presentation.metadata.SessionId) ?? null) await moveToRoom(x, y, currentInfo, currentPerson, room, getMetadata(presentation.metadata.SessionId) ?? null)
await connectLK(currentPerson, room)
selectedRoomPlace.set(undefined) selectedRoomPlace.set(undefined)
await openMeetingMinutes(room) try {
await withRetries(
async () => {
await connectLK(currentPerson, room)
},
3,
1000
)
await openMeetingMinutes(room)
} catch (err) {
console.error(err)
await leaveRoom(currentInfo, get(myOffice))
}
} }
export const joinRequest: Ref<JoinRequest> | undefined = undefined export const joinRequest: Ref<JoinRequest> | undefined = undefined

View File

@ -16,6 +16,7 @@ import core, {
import love, { import love, {
getFreeRoomPlace, getFreeRoomPlace,
MeetingMinutes, MeetingMinutes,
MeetingStatus,
ParticipantInfo, ParticipantInfo,
Room, Room,
RoomLanguage, RoomLanguage,
@ -216,7 +217,9 @@ export class LoveController {
if (sid === '') return undefined if (sid === '') return undefined
const doc = const doc =
this.meetingMinutes.find((m) => m.sid === sid) ?? (await this.client.findOne(love.class.MeetingMinutes, { sid })) this.meetingMinutes.find(
(m) => m.sid === sid && m.attachedTo === room._id && m.status === MeetingStatus.Active
) ?? (await this.client.findOne(love.class.MeetingMinutes, { sid, room: room._id, status: MeetingStatus.Active }))
if (doc === undefined) { if (doc === undefined) {
return undefined return undefined