diff --git a/plugins/love-assets/assets/icons.svg b/plugins/love-assets/assets/icons.svg
index 73fe21ad87..4e7d4cc5b3 100644
--- a/plugins/love-assets/assets/icons.svg
+++ b/plugins/love-assets/assets/icons.svg
@@ -89,4 +89,9 @@
+
+
+
+
+
diff --git a/plugins/love-assets/lang/cs.json b/plugins/love-assets/lang/cs.json
index 6c86bad07f..9b9c1f33c6 100644
--- a/plugins/love-assets/lang/cs.json
+++ b/plugins/love-assets/lang/cs.json
@@ -75,10 +75,12 @@
"JoinMeeting": "Připojit se ke schůzce",
"MeetingStart": "Začátek schůzky",
"MeetingEnd": "Konec schůzky",
+ "EndMeeting": "Ukončit schůzku",
"Status": "Stav",
"Active": "Aktivní",
"Finished": "Dokončeno",
"StartWithRecording": "Začít s nahráváním",
- "Language": "Jazyk"
+ "Language": "Jazyk",
+ "Kick": "Vyhodit"
}
}
\ No newline at end of file
diff --git a/plugins/love-assets/lang/en.json b/plugins/love-assets/lang/en.json
index 22cc2923a9..d86279790c 100644
--- a/plugins/love-assets/lang/en.json
+++ b/plugins/love-assets/lang/en.json
@@ -75,10 +75,12 @@
"JoinMeeting": "Join meeting",
"MeetingStart": "Meeting start",
"MeetingEnd": "Meeting end",
+ "EndMeeting": "End meeting",
"Status": "Status",
"Active": "Active",
"Finished": "Finished",
"StartWithRecording": "Start with recording",
- "Language": "Language"
+ "Language": "Language",
+ "Kick": "Kick"
}
}
diff --git a/plugins/love-assets/lang/es.json b/plugins/love-assets/lang/es.json
index 8a50a54be6..d51bb0d0da 100644
--- a/plugins/love-assets/lang/es.json
+++ b/plugins/love-assets/lang/es.json
@@ -75,10 +75,12 @@
"JoinMeeting": "Unirse a la reunión",
"MeetingStart": "Inicio de la reunión",
"MeetingEnd": "Fin de la reunión",
+ "EndMeeting": "Terminar reunión",
"Status": "Estado",
"Active": "Activo",
"Finished": "Terminado",
"StartWithRecording": "Iniciar con grabación",
- "Language": "Idioma"
+ "Language": "Idioma",
+ "Kick": "Expulsar"
}
}
diff --git a/plugins/love-assets/lang/fr.json b/plugins/love-assets/lang/fr.json
index 1c93c733a0..3f602a4675 100644
--- a/plugins/love-assets/lang/fr.json
+++ b/plugins/love-assets/lang/fr.json
@@ -75,10 +75,12 @@
"JoinMeeting": "Rejoindre la réunion",
"MeetingStart": "Début de la réunion",
"MeetingEnd": "Fin de la réunion",
+ "EndMeeting": "Terminer la réunion",
"Status": "Statut",
"Active": "Actif",
"Finished": "Terminé",
"StartWithRecording": "Démarrer avec l'enregistrement",
- "Language": "Langue"
+ "Language": "Langue",
+ "Kick": "Expulser"
}
}
\ No newline at end of file
diff --git a/plugins/love-assets/lang/it.json b/plugins/love-assets/lang/it.json
index aa569589fd..1a2bf3700a 100644
--- a/plugins/love-assets/lang/it.json
+++ b/plugins/love-assets/lang/it.json
@@ -75,10 +75,12 @@
"JoinMeeting": "Unisciti alla riunione",
"MeetingStart": "Inizio riunione",
"MeetingEnd": "Fine riunione",
+ "EndMeeting": "Termina riunione",
"Status": "Stato",
"Active": "Attivo",
"Finished": "Finito",
"StartWithRecording": "Inizia con la registrazione",
- "Language": "Lingua"
+ "Language": "Lingua",
+ "Kick": "Espellere"
}
}
diff --git a/plugins/love-assets/lang/pt.json b/plugins/love-assets/lang/pt.json
index 28491c92a8..6547a98695 100644
--- a/plugins/love-assets/lang/pt.json
+++ b/plugins/love-assets/lang/pt.json
@@ -75,10 +75,12 @@
"JoinMeeting": "Participar na reunião",
"MeetingStart": "Início da reunião",
"MeetingEnd": "Fim da reunião",
+ "EndMeeting": "Terminar reunião",
"Status": "Estado",
"Active": "Ativo",
"Finished": "Finalizado",
"StartWithRecording": "Começar com gravação",
- "Language": "Idioma"
+ "Language": "Idioma",
+ "Kick": "Expulsar"
}
}
diff --git a/plugins/love-assets/lang/ru.json b/plugins/love-assets/lang/ru.json
index 95ecdf8082..c430ccfb9b 100644
--- a/plugins/love-assets/lang/ru.json
+++ b/plugins/love-assets/lang/ru.json
@@ -75,10 +75,12 @@
"JoinMeeting": "Присоединиться к встрече",
"MeetingStart": "Начало встречи",
"MeetingEnd": "Конец встречи",
+ "EndMeeting": "Завершить встречу",
"Status": "Статус",
"Active": "Активно",
"Finished": "Завершено",
"StartWithRecording": "Начинать с записью",
- "Language": "Язык"
+ "Language": "Язык",
+ "Kick": "Выгнать"
}
}
diff --git a/plugins/love-assets/lang/zh.json b/plugins/love-assets/lang/zh.json
index a665270a73..8c7415331e 100644
--- a/plugins/love-assets/lang/zh.json
+++ b/plugins/love-assets/lang/zh.json
@@ -75,10 +75,12 @@
"JoinMeeting": "加入会议",
"MeetingStart": "会议开始",
"MeetingEnd": "会议结束",
+ "EndMeeting": "结束会议",
"Status": "状态",
"Active": "活动",
"Finished": "已完成",
"StartWithRecording": "开始录制",
- "Language": "语言"
+ "Language": "语言",
+ "Kick": "踢出"
}
}
diff --git a/plugins/love-assets/src/index.ts b/plugins/love-assets/src/index.ts
index 6e1f80e6cf..6ff830192f 100644
--- a/plugins/love-assets/src/index.ts
+++ b/plugins/love-assets/src/index.ts
@@ -36,7 +36,8 @@ loadMetadata(love.icon, {
StopRecord: `${icons}#stopRecord`,
FullScreen: `${icons}#fullscreen`,
ExitFullScreen: `${icons}#exitfullscreen`,
- Invite: `${icons}#invite`
+ Invite: `${icons}#invite`,
+ Kick: `${icons}#kick`
})
loadMetadata(love.sound, {
Knock: require('../assets/knock.wav')
diff --git a/plugins/love-resources/src/components/ControlExt.svelte b/plugins/love-resources/src/components/ControlExt.svelte
index 7ad226a8cf..1ecbd2ad66 100644
--- a/plugins/love-resources/src/components/ControlExt.svelte
+++ b/plugins/love-resources/src/components/ControlExt.svelte
@@ -14,7 +14,7 @@
-->
{/if}
- {#if $location.path[2] !== loveId || (joined && allowLeave) || !joined}
+ {#if $location.path[2] !== loveId || (joined && (allowLeave || isMyOffice)) || !joined}
- {#if joined && allowLeave}
-
- {:else if !joined}
+ {#if joined}
+ {#if allowLeave}
+
+ {:else if isMyOffice}
+
+ {/if}
+ {:else}
- import { pushRootBarComponent, rootBarExtensions } from '@hcengineering/ui'
+ import { pushRootBarComponent } from '@hcengineering/ui'
import { RemoteParticipant, RemoteTrack, RemoteTrackPublication, RoomEvent, Track } from 'livekit-client'
import { onDestroy, onMount } from 'svelte'
import love from '../plugin'
import { disconnect, isCurrentInstanceConnected, lk } from '../utils'
- import { generateId } from '@hcengineering/core'
let parentElement: HTMLDivElement
diff --git a/plugins/love-resources/src/utils.ts b/plugins/love-resources/src/utils.ts
index 17bbe4c6c6..3dc80d9e00 100644
--- a/plugins/love-resources/src/utils.ts
+++ b/plugins/love-resources/src/utils.ts
@@ -1,19 +1,22 @@
+import aiBot from '@hcengineering/ai-bot'
+import { connectMeeting, disconnectMeeting } from '@hcengineering/ai-bot-resources'
import { Analytics } from '@hcengineering/analytics'
import calendar, { type Event, getAllEvents } from '@hcengineering/calendar'
+import chunter from '@hcengineering/chunter'
import contact, { getName, type Person, type PersonAccount } from '@hcengineering/contact'
import { personByIdStore } from '@hcengineering/contact-resources'
import core, {
AccountRole,
concatLink,
type Data,
+ type Doc,
generateId,
getCurrentAccount,
+ type Hierarchy,
type IdMap,
type Ref,
type Space,
- type TxOperations,
- type Hierarchy,
- type Doc
+ type TxOperations
} from '@hcengineering/core'
import login from '@hcengineering/login'
import {
@@ -24,16 +27,16 @@ import {
LoveEvents,
loveId,
type Meeting,
+ type MeetingMinutes,
+ MeetingStatus,
type Office,
type ParticipantInfo,
RequestStatus,
type Room,
RoomAccess,
- RoomType,
- TranscriptionStatus,
type RoomMetadata,
- type MeetingMinutes,
- MeetingStatus
+ RoomType,
+ TranscriptionStatus
} from '@hcengineering/love'
import { getEmbeddedLabel, getMetadata, getResource, type IntlString } from '@hcengineering/platform'
import presentation, {
@@ -43,18 +46,29 @@ import presentation, {
getClient
} from '@hcengineering/presentation'
import {
+ closePanel,
type DropdownTextItem,
getCurrentLocation,
navigate,
- showPopup,
panelstore,
- closePanel
+ showPopup
} from '@hcengineering/ui'
+import view from '@hcengineering/view'
+import { getObjectLinkFragment } from '@hcengineering/view-resources'
+import { type Widget, type WidgetTab } from '@hcengineering/workbench'
+import {
+ currentWorkspaceStore,
+ openWidget,
+ openWidgetTab,
+ sidebarStore,
+ updateWidgetState
+} from '@hcengineering/workbench-resources'
import { isKrispNoiseFilterSupported, KrispNoiseFilter } from '@livekit/krisp-noise-filter'
import { BackgroundBlur, type BackgroundOptions, type ProcessorWrapper } from '@livekit/track-processors'
import {
type AudioCaptureOptions,
ConnectionState,
+ Room as LKRoom,
LocalAudioTrack,
type LocalTrack,
type LocalTrackPublication,
@@ -62,30 +76,16 @@ import {
type RemoteParticipant,
type RemoteTrack,
type RemoteTrackPublication,
- Room as LKRoom,
RoomEvent,
Track,
type VideoCaptureOptions
} from 'livekit-client'
import { get, writable } from 'svelte/store'
-import aiBot from '@hcengineering/ai-bot'
-import { connectMeeting, disconnectMeeting } from '@hcengineering/ai-bot-resources'
-import {
- openWidget,
- sidebarStore,
- updateWidgetState,
- currentWorkspaceStore,
- openWidgetTab
-} from '@hcengineering/workbench-resources'
-import { type Widget, type WidgetTab } from '@hcengineering/workbench'
-import view from '@hcengineering/view'
-import chunter from '@hcengineering/chunter'
-import { getObjectLinkFragment } from '@hcengineering/view-resources'
import { sendMessage } from './broadcast'
-import love from './plugin'
-import { $myPreferences, currentRoom, currentMeetingMinutes, selectedRoomPlace, myOffice } from './stores'
import RoomSettingsPopup from './components/RoomSettingsPopup.svelte'
+import love from './plugin'
+import { $myPreferences, currentMeetingMinutes, currentRoom, myOffice, selectedRoomPlace } from './stores'
export const selectedCamId = 'selectedDevice_cam'
export const selectedMicId = 'selectedDevice_mic'
@@ -860,6 +860,27 @@ export async function tryConnect (
}
}
+export async function endMeeting (
+ room: Office,
+ rooms: Room[],
+ infos: ParticipantInfo[],
+ currentInfo: ParticipantInfo
+): Promise {
+ const roomInfos = infos.filter((p) => p.room === room._id && room.person !== p.person)
+ for (const roomInfo of roomInfos) {
+ await kick(roomInfo.person, rooms, infos)
+ }
+ await leaveRoom(currentInfo, room)
+}
+
+export async function kick (person: Ref, rooms: Room[], infos: ParticipantInfo[]): Promise {
+ const personInfo = infos.find((p) => p.person === person)
+ if (personInfo === undefined) return
+ const personOffice = rooms.find((r) => isOffice(r) && r.person === personInfo.person)
+ const client = getClient()
+ await client.update(personInfo, { room: personOffice?._id ?? love.ids.Reception, x: 0, y: 0 })
+}
+
export async function invite (person: Ref, room: Ref | undefined): Promise {
if (room === undefined || room === love.ids.Reception) return
const client = getClient()
diff --git a/plugins/love/src/index.ts b/plugins/love/src/index.ts
index 33c4e1790b..cbb774f2b5 100644
--- a/plugins/love/src/index.ts
+++ b/plugins/love/src/index.ts
@@ -225,7 +225,9 @@ const love = plugin(loveId, {
Status: '' as IntlString,
Active: '' as IntlString,
Finished: '' as IntlString,
- StartWithRecording: '' as IntlString
+ StartWithRecording: '' as IntlString,
+ Kick: '' as IntlString,
+ EndMeeting: '' as IntlString
},
ids: {
MainFloor: '' as Ref,
@@ -254,7 +256,8 @@ const love = plugin(loveId, {
StopRecord: '' as Asset,
FullScreen: '' as Asset,
ExitFullScreen: '' as Asset,
- Invite: '' as Asset
+ Invite: '' as Asset,
+ Kick: '' as Asset
},
sound: {
Knock: '' as Asset