Compare commits
13 Commits
b3a1419ed3
...
v0.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7c619c872 | ||
|
|
408d3635f6 | ||
|
|
ff2dd60a95 | ||
|
|
bb07744081 | ||
|
|
8c57fd9d7b | ||
|
|
4d9cd25b19 | ||
|
|
2cff9c79a7 | ||
|
|
beea7fcb17 | ||
|
|
7f60048a9d | ||
|
|
c912ec8387 | ||
|
|
f6ad918d00 | ||
|
|
0a2b48a630 | ||
|
|
c336b62885 |
66
README.md
66
README.md
@@ -1,65 +1,3 @@
|
||||
# Svelte library
|
||||
# Jitsi iFrame Svelte Integration
|
||||
|
||||
Everything you need to build a Svelte library, powered by [`sv`](https://npmjs.com/package/sv).
|
||||
|
||||
Read more about creating a library [in the docs](https://svelte.dev/docs/kit/packaging).
|
||||
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```sh
|
||||
# create a new project in the current directory
|
||||
npx sv create
|
||||
|
||||
# create a new project in my-app
|
||||
npx sv create my-app
|
||||
```
|
||||
|
||||
To recreate this project with the same configuration:
|
||||
|
||||
```sh
|
||||
# recreate this project
|
||||
pnpm dlx sv create --template library --types ts --add prettier eslint devtools-json --install pnpm jitsi
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
Everything inside `src/lib` is part of your library, everything inside `src/routes` can be used as a showcase or preview app.
|
||||
|
||||
## Building
|
||||
|
||||
To build your library:
|
||||
|
||||
```sh
|
||||
npm pack
|
||||
```
|
||||
|
||||
To create a production version of your showcase app:
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
||||
|
||||
## Publishing
|
||||
|
||||
Go into the `package.json` and give your package the desired name through the `"name"` option. Also consider adding a `"license"` field and point it to a `LICENSE` file which you can create from a template (one popular option is the [MIT license](https://opensource.org/license/mit/)).
|
||||
|
||||
To publish your library to [npm](https://www.npmjs.com):
|
||||
|
||||
```sh
|
||||
npm publish
|
||||
```
|
||||
This package provides a component and typed API for the Jitsi Meet iFrame. If you prefer to build your own component, refer directly to the exported type definitions for the Jitsi iFrame API.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "@svelte-toolkit/jitsi",
|
||||
"version": "0.0.2",
|
||||
"version": "0.1.0",
|
||||
"license": "BSD-3-Clause",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://gitea.auvem.com/svelte-toolkit/jitsi.git"
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
<!-- @component
|
||||
The Jitsi component is a lightweight wrapper that manages loading the Jitsi Meet External API
|
||||
and joining a Jitsi meeting room. It accepts configuration options and several callbacks that
|
||||
allow you to respond to basic meeting events such as joining and leaving. For advanced event
|
||||
handling, use the getAPI() method to interact with the Jitsi instance directly.
|
||||
|
||||
WARNING: While properties are reactive, in most cases changing them after the API has
|
||||
initialized will trigger a complete re-render of the component, which will destroy the
|
||||
existing Jitsi instance and interrupt any ongoing meetings. Use the getAPI() method to
|
||||
interact with the Jitsi instance directly without causing a re-render.
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { type JitsiMeetExternalAPIOptions, JitsiMeetExternalAPI } from './jitsi-iframe-api.js';
|
||||
import { onMount, type Snippet } from 'svelte';
|
||||
import type {
|
||||
JitsiMeetExternalAPIOptions,
|
||||
JitsiMeetExternalAPI,
|
||||
VideoConferenceJoinedEvent,
|
||||
VideoConferenceLeftEvent
|
||||
} from '$lib/jitsi-iframe-api.d.ts';
|
||||
import type { ClassValue } from 'svelte/elements';
|
||||
|
||||
interface Props {
|
||||
@@ -18,27 +35,95 @@
|
||||
* Additional CSS classes to apply to the Jitsi container.
|
||||
*/
|
||||
class?: ClassValue;
|
||||
/**
|
||||
* Optional snippet rendered until the API is initialized and the meeting
|
||||
* is joined. Can be used to provide a loading indicator or placeholder content.
|
||||
*/
|
||||
loading?: Snippet;
|
||||
/** Whether to hold loading state until the meeting is joined (default: false). */
|
||||
holdLoadingUntilJoined?: boolean;
|
||||
/**
|
||||
* Optional snippet rendered after the API is initialized and the meeting is joined.
|
||||
* Can be used to provide additional UI elements or controls related to the meeting.
|
||||
* Overlay has pointer-events disabled to allow interaction with the underlying Jitsi
|
||||
* interface.
|
||||
*/
|
||||
joinedOverlay?: Snippet<[api: JitsiMeetExternalAPI]>;
|
||||
/**
|
||||
* Callback function that is called when the Jitsi API is loaded. Can
|
||||
* be used to provide a loading indicator until the API is ready.
|
||||
* @param api The Jitsi Meet External API instance.
|
||||
*/
|
||||
onapiready?: (api: JitsiMeetExternalAPI) => void;
|
||||
/** Callback triggered when the local user joins the meeting. */
|
||||
onjoin?: (ev: VideoConferenceJoinedEvent) => void;
|
||||
/** Callback triggered when the local user leaves the meeting. */
|
||||
onleave?: (ev: VideoConferenceLeftEvent) => void;
|
||||
}
|
||||
|
||||
let { domain = 'https://meet.jit.si', options, class: classValue }: Props = $props();
|
||||
let {
|
||||
domain = 'https://meet.jit.si',
|
||||
options,
|
||||
class: classValue,
|
||||
loading,
|
||||
holdLoadingUntilJoined = false,
|
||||
joinedOverlay,
|
||||
onapiready,
|
||||
onjoin,
|
||||
onleave
|
||||
}: Props = $props();
|
||||
|
||||
const src = $derived(`${new URL('external_api.js', domain).toString()}`);
|
||||
|
||||
let container: HTMLDivElement;
|
||||
/** tracks whether the Jitsi API is ready */
|
||||
let apiReady = $state(false);
|
||||
/** tracks whether the local user has joined the meeting */
|
||||
let joinedMeeting = $state(false);
|
||||
/** tracks whether the local user has left the meeting */
|
||||
let leftMeeting = $state(false);
|
||||
/** whether to display the loading state */
|
||||
const showLoading = $derived(holdLoadingUntilJoined ? !joinedMeeting : !apiReady);
|
||||
|
||||
let api = $state<JitsiMeetExternalAPI | null>(null);
|
||||
|
||||
onMount(() => {
|
||||
// check if we have a duplicate container
|
||||
if (document.querySelectorAll('#jitsi-container').length > 1) {
|
||||
if (document.querySelectorAll('#jitsi-iframe').length > 1) {
|
||||
console.warn('Duplicate Jitsi container detected. This may lead to unexpected behavior.');
|
||||
}
|
||||
});
|
||||
|
||||
/** handles Jitsi script load event */
|
||||
const handleScriptLoad = () => {
|
||||
if (typeof window.JitsiMeetExternalAPI === 'undefined') {
|
||||
console.error('Jitsi Meet External API is not available on the window object.');
|
||||
return;
|
||||
}
|
||||
|
||||
apiReady = true;
|
||||
// Initialize the Jitsi Meet External API
|
||||
api = new JitsiMeetExternalAPI(new URL(domain).host, {
|
||||
api = new window.JitsiMeetExternalAPI(new URL(domain).host, {
|
||||
...options,
|
||||
parentNode: container
|
||||
});
|
||||
});
|
||||
if (api === null) {
|
||||
console.error('Failed to initialize Jitsi Meet External API.');
|
||||
return;
|
||||
}
|
||||
// Call the onapiready callback if provided
|
||||
onapiready?.(api);
|
||||
|
||||
// Attach event listeners for meeting join and leave events
|
||||
api.addListener('videoConferenceJoined', (ev: VideoConferenceJoinedEvent) => {
|
||||
joinedMeeting = true;
|
||||
onjoin?.(ev);
|
||||
});
|
||||
api.addListener('videoConferenceLeft', (ev: VideoConferenceLeftEvent) => {
|
||||
leftMeeting = true;
|
||||
onleave?.(ev);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the Jitsi Meet External API instance.
|
||||
@@ -50,7 +135,43 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<script {src}></script>
|
||||
<script {src} onload={handleScriptLoad}></script>
|
||||
</svelte:head>
|
||||
|
||||
<div id="jitsi-container" bind:this={container} class={[classValue]}></div>
|
||||
<div class={['jitsi-container', classValue]}>
|
||||
{#if showLoading}
|
||||
<div class="overlay-container">{@render loading?.()}</div>
|
||||
{/if}
|
||||
|
||||
{#if joinedMeeting && api && joinedOverlay}
|
||||
<div class="overlay-container passthrough">{@render joinedOverlay(api)}</div>
|
||||
{/if}
|
||||
|
||||
<div
|
||||
id="jitsi-iframe"
|
||||
bind:this={container}
|
||||
class="fill-container"
|
||||
style={leftMeeting ? 'display: none;' : undefined}
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<style lang="css">
|
||||
.jitsi-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fill-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-width: 0px;
|
||||
}
|
||||
|
||||
.overlay-container {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
.passthrough {
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
555
src/lib/jitsi-iframe-api.d.ts
vendored
555
src/lib/jitsi-iframe-api.d.ts
vendored
@@ -438,28 +438,521 @@ export interface JitsiMeetExternalAPIOptions {
|
||||
}
|
||||
|
||||
interface ConfigOverwrite {
|
||||
// Audio settings
|
||||
startWithAudioMuted?: boolean;
|
||||
startWithVideoMuted?: boolean;
|
||||
disableDeepLinking?: boolean;
|
||||
prejoinPageEnabled?: boolean;
|
||||
startAudioMuted?: number;
|
||||
startAudioOnly?: boolean;
|
||||
startSilent?: boolean;
|
||||
enableNoisyMicDetection?: boolean;
|
||||
enableOpusRed?: boolean;
|
||||
audioQuality?: {
|
||||
stereo?: boolean;
|
||||
opusMaxAverageBitrate?: number | null;
|
||||
enableOpusDtx?: boolean;
|
||||
};
|
||||
noiseSuppression?: {
|
||||
krisp?: {
|
||||
enabled?: boolean;
|
||||
logProcessStats?: boolean;
|
||||
debugLogs?: boolean;
|
||||
useBVC?: boolean;
|
||||
bufferOverflowMS?: number;
|
||||
};
|
||||
};
|
||||
disableAEC?: boolean;
|
||||
disableAGC?: boolean;
|
||||
disableAP?: boolean;
|
||||
disableNS?: boolean;
|
||||
|
||||
// Video settings
|
||||
startWithVideoMuted?: boolean;
|
||||
startVideoMuted?: number;
|
||||
maxFullResolutionParticipants?: number;
|
||||
disableSimulcast?: boolean;
|
||||
disableResponsiveTiles?: boolean;
|
||||
constraints?: {
|
||||
video?: {
|
||||
height?: {
|
||||
ideal?: number;
|
||||
max?: number;
|
||||
min?: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
desktopSharingFrameRate?: {
|
||||
min?: number;
|
||||
max?: number;
|
||||
};
|
||||
screenShareSettings?: {
|
||||
desktopPreferCurrentTab?: boolean;
|
||||
desktopSystemAudio?: 'include' | 'exclude';
|
||||
desktopSurfaceSwitching?: 'include' | 'exclude';
|
||||
desktopDisplaySurface?: string;
|
||||
desktopSelfBrowserSurface?: 'include' | 'exclude';
|
||||
};
|
||||
videoQuality?: {
|
||||
codecPreferenceOrder?: ('AV1' | 'VP9' | 'VP8' | 'H264')[];
|
||||
mobileCodecPreferenceOrder?: ('AV1' | 'VP9' | 'VP8' | 'H264')[];
|
||||
screenshareCodec?: string;
|
||||
mobileScreenshareCodec?: string;
|
||||
enableAdaptiveMode?: boolean;
|
||||
minHeightForQualityLvl?: Record<number, 'low' | 'standard' | 'high'>;
|
||||
};
|
||||
|
||||
// Prejoin configuration (replaces prejoinPageEnabled)
|
||||
prejoinConfig?: {
|
||||
enabled?: boolean;
|
||||
hideDisplayName?: boolean;
|
||||
hideExtraJoinButtons?: ('no-audio' | 'by-phone')[];
|
||||
preCallTestEnabled?: boolean;
|
||||
preCallTestICEUrl?: string;
|
||||
showHangUp?: boolean;
|
||||
};
|
||||
/** @deprecated Use prejoinConfig.enabled instead */
|
||||
prejoinPageEnabled?: boolean;
|
||||
|
||||
// Lobby configuration
|
||||
lobby?: {
|
||||
autoKnock?: boolean;
|
||||
enableChat?: boolean;
|
||||
showHangUp?: boolean;
|
||||
};
|
||||
/** @deprecated Use lobby.autoKnock instead */
|
||||
autoKnockLobby?: boolean;
|
||||
/** @deprecated Use lobby.enableChat instead */
|
||||
enableLobbyChat?: boolean;
|
||||
|
||||
// Security UI configuration
|
||||
securityUi?: {
|
||||
hideLobbyButton?: boolean;
|
||||
disableLobbyPassword?: boolean;
|
||||
};
|
||||
/** @deprecated Use securityUi.hideLobbyButton instead */
|
||||
hideLobbyButton?: boolean;
|
||||
|
||||
// Deep linking configuration
|
||||
deeplinking?: {
|
||||
disabled?: boolean;
|
||||
hideLogo?: boolean;
|
||||
desktop?: {
|
||||
appName?: string;
|
||||
appScheme?: string;
|
||||
download?: {
|
||||
linux?: string;
|
||||
macos?: string;
|
||||
windows?: string;
|
||||
};
|
||||
enabled?: boolean;
|
||||
};
|
||||
ios?: {
|
||||
appName?: string;
|
||||
appScheme?: string;
|
||||
downloadLink?: string;
|
||||
};
|
||||
android?: {
|
||||
appName?: string;
|
||||
appScheme?: string;
|
||||
downloadLink?: string;
|
||||
appPackage?: string;
|
||||
fDroidUrl?: string;
|
||||
};
|
||||
};
|
||||
/** @deprecated Use deeplinking.disabled instead */
|
||||
disableDeepLinking?: boolean;
|
||||
|
||||
// Welcome page configuration
|
||||
welcomePage?: {
|
||||
disabled?: boolean;
|
||||
customUrl?: string;
|
||||
};
|
||||
|
||||
// Recording configuration
|
||||
recordings?: {
|
||||
recordAudioAndVideo?: boolean;
|
||||
suggestRecording?: boolean;
|
||||
showPrejoinWarning?: boolean;
|
||||
showRecordingLink?: boolean;
|
||||
requireConsent?: boolean;
|
||||
skipConsentInMeeting?: boolean;
|
||||
consentLearnMoreLink?: string;
|
||||
};
|
||||
recordingService?: {
|
||||
enabled?: boolean;
|
||||
sharingEnabled?: boolean;
|
||||
hideStorageWarning?: boolean;
|
||||
};
|
||||
localRecording?: {
|
||||
disable?: boolean;
|
||||
notifyAllParticipants?: boolean;
|
||||
disableSelfRecording?: boolean;
|
||||
};
|
||||
|
||||
// Live streaming configuration
|
||||
liveStreaming?: {
|
||||
enabled?: boolean;
|
||||
termsLink?: string;
|
||||
dataPrivacyLink?: string;
|
||||
validatorRegExpString?: string;
|
||||
helpLink?: string;
|
||||
};
|
||||
|
||||
// Transcription configuration
|
||||
transcription?: {
|
||||
enabled?: boolean;
|
||||
useAppLanguage?: boolean;
|
||||
preferredLanguage?: string;
|
||||
customLanguages?: Record<string, string>;
|
||||
autoTranscribeOnRecord?: boolean;
|
||||
autoCaptionOnTranscribe?: boolean;
|
||||
disableClosedCaptions?: boolean;
|
||||
};
|
||||
|
||||
// Toolbar configuration
|
||||
toolbarButtons?: ToolbarButton[];
|
||||
mainToolbarButtons?: ToolbarButton[][];
|
||||
reducedUImainToolbarButtons?: ToolbarButton[];
|
||||
reducedUIEnabled?: boolean;
|
||||
buttonsWithNotifyClick?: (ToolbarButton | ButtonWithNotifyClick)[];
|
||||
participantMenuButtonsWithNotifyClick?: (string | ButtonWithNotifyClick)[];
|
||||
hiddenPremeetingButtons?: (
|
||||
| 'microphone'
|
||||
| 'camera'
|
||||
| 'select-background'
|
||||
| 'invite'
|
||||
| 'settings'
|
||||
)[];
|
||||
customToolbarButtons?: Array<{
|
||||
icon: string;
|
||||
id: string;
|
||||
text: string;
|
||||
backgroundColor?: string;
|
||||
}>;
|
||||
customParticipantMenuButtons?: Array<{ icon: string; id: string; text: string }>;
|
||||
toolbar?: {
|
||||
initialTimeout?: number;
|
||||
timeout?: number;
|
||||
alwaysVisible?: boolean;
|
||||
autoHideWhileChatIsOpen?: boolean;
|
||||
};
|
||||
|
||||
// UI settings
|
||||
enableClosePage?: boolean;
|
||||
disableInviteFunctions?: boolean;
|
||||
disableModeratorIndicator?: boolean;
|
||||
enableLobbyChat?: boolean;
|
||||
hideLobbyButton?: boolean;
|
||||
enableInsecureRoomNameWarning?: boolean;
|
||||
toolbarButtons?: ToolbarButton[];
|
||||
buttonsWithNotifyClick?: (ToolbarButton | ButtonWithNotifyClick)[];
|
||||
mouseMoveCallbackInterval?: number;
|
||||
faceLandmarks?: {
|
||||
faceCenteringThreshold?: number;
|
||||
disableReactions?: boolean;
|
||||
disableReactionsModeration?: boolean;
|
||||
disableReactionsInChat?: boolean;
|
||||
disablePolls?: boolean;
|
||||
disableChat?: boolean;
|
||||
disableSelfDemote?: boolean;
|
||||
disableSelfView?: boolean;
|
||||
disableSelfViewSettings?: boolean;
|
||||
showChatPermissionsModeratorSetting?: boolean;
|
||||
disableShortcuts?: boolean;
|
||||
disableInitialGUM?: boolean;
|
||||
disable1On1Mode?: boolean | null;
|
||||
defaultLocalDisplayName?: string;
|
||||
defaultRemoteDisplayName?: string;
|
||||
hideDisplayName?: boolean;
|
||||
hideDominantSpeakerBadge?: boolean;
|
||||
defaultLanguage?: string;
|
||||
disableProfile?: boolean;
|
||||
hideEmailInSettings?: boolean;
|
||||
requireDisplayName?: boolean;
|
||||
readOnlyName?: boolean;
|
||||
enableWebHIDFeature?: boolean;
|
||||
doNotStoreRoom?: boolean;
|
||||
disableLocalVideoFlip?: boolean;
|
||||
doNotFlipLocalVideo?: boolean;
|
||||
disableVirtualBackground?: boolean;
|
||||
disableAddingBackgroundImages?: boolean;
|
||||
backgroundAlpha?: number;
|
||||
disableTileView?: boolean;
|
||||
disableTileEnlargement?: boolean;
|
||||
hideConferenceSubject?: boolean;
|
||||
hideConferenceTimer?: boolean;
|
||||
hideRecordingLabel?: boolean;
|
||||
hideParticipantsStats?: boolean;
|
||||
subject?: string;
|
||||
localSubject?: string;
|
||||
disableChatSmileys?: boolean;
|
||||
disableFilmstripAutohiding?: boolean;
|
||||
disableCameraTintForeground?: boolean;
|
||||
|
||||
// Filmstrip configuration
|
||||
filmstrip?: {
|
||||
disabled?: boolean;
|
||||
disableResizable?: boolean;
|
||||
disableStageFilmstrip?: boolean;
|
||||
stageFilmstripParticipants?: number;
|
||||
disableTopPanel?: boolean;
|
||||
minParticipantCountForTopPanel?: number;
|
||||
initialWidth?: number;
|
||||
alwaysShowResizeBar?: boolean;
|
||||
};
|
||||
|
||||
// Tile view configuration
|
||||
tileView?: {
|
||||
disabled?: boolean;
|
||||
numberOfVisibleTiles?: number;
|
||||
};
|
||||
|
||||
// Participants pane configuration
|
||||
participantsPane?: {
|
||||
enabled?: boolean;
|
||||
hideModeratorSettingsTab?: boolean;
|
||||
hideMoreActionsButton?: boolean;
|
||||
hideMuteAllButton?: boolean;
|
||||
};
|
||||
|
||||
// Breakout rooms configuration
|
||||
breakoutRooms?: {
|
||||
hideAddRoomButton?: boolean;
|
||||
hideAutoAssignButton?: boolean;
|
||||
hideJoinRoomButton?: boolean;
|
||||
};
|
||||
|
||||
// Raised hands configuration
|
||||
raisedHands?: {
|
||||
disableLowerHandByModerator?: boolean;
|
||||
disableLowerHandNotification?: boolean;
|
||||
disableNextSpeakerNotification?: boolean;
|
||||
disableRemoveRaisedHandOnFocus?: boolean;
|
||||
};
|
||||
disableRemoveRaisedHandOnFocus?: boolean;
|
||||
|
||||
// Speaker stats configuration
|
||||
speakerStats?: {
|
||||
disabled?: boolean;
|
||||
disableSearch?: boolean;
|
||||
order?: ('role' | 'name' | 'hasLeft')[];
|
||||
};
|
||||
|
||||
// Connection indicators configuration
|
||||
connectionIndicators?: {
|
||||
autoHide?: boolean;
|
||||
autoHideTimeout?: number;
|
||||
disabled?: boolean;
|
||||
disableDetails?: boolean;
|
||||
inactiveDisabled?: boolean;
|
||||
};
|
||||
|
||||
// Remote video menu configuration
|
||||
remoteVideoMenu?: {
|
||||
disabled?: boolean;
|
||||
disableDemote?: boolean;
|
||||
disableKick?: boolean;
|
||||
disableGrantModerator?: boolean;
|
||||
disablePrivateChat?: 'all' | 'allow-moderator-chat' | 'disable-visitor-chat';
|
||||
};
|
||||
disableRemoteMute?: boolean;
|
||||
|
||||
// Face landmarks configuration
|
||||
faceLandmarks?: {
|
||||
enableFaceCentering?: boolean;
|
||||
enableFaceExpressionsDetection?: boolean;
|
||||
enableDisplayFaceExpressions?: boolean;
|
||||
enableRTCStats?: boolean;
|
||||
faceCenteringThreshold?: number;
|
||||
captureInterval?: number;
|
||||
};
|
||||
|
||||
// Notification settings
|
||||
notificationTimeouts?: {
|
||||
short?: number;
|
||||
medium?: number;
|
||||
long?: number;
|
||||
extraLong?: number;
|
||||
sticky?: number;
|
||||
};
|
||||
notifications?: string[];
|
||||
disabledNotifications?: string[];
|
||||
|
||||
// Conference info configuration
|
||||
conferenceInfo?: {
|
||||
alwaysVisible?: string[];
|
||||
autoHide?: string[];
|
||||
};
|
||||
|
||||
// Giphy configuration
|
||||
giphy?: {
|
||||
enabled?: boolean;
|
||||
sdkKey?: string;
|
||||
displayMode?: 'tile' | 'chat' | 'all';
|
||||
tileTime?: number;
|
||||
rating?: 'g' | 'pg' | 'pg-13' | 'r';
|
||||
};
|
||||
|
||||
// Whiteboard configuration
|
||||
whiteboard?: {
|
||||
enabled?: boolean;
|
||||
collabServerBaseUrl?: string;
|
||||
userLimit?: number;
|
||||
limitUrl?: string;
|
||||
};
|
||||
|
||||
// E2EE configuration
|
||||
e2ee?: {
|
||||
labels?: {
|
||||
description?: string;
|
||||
label?: string;
|
||||
tooltip?: string;
|
||||
warning?: string;
|
||||
};
|
||||
externallyManagedKey?: boolean;
|
||||
};
|
||||
|
||||
// Visitors configuration
|
||||
visitors?: {
|
||||
enableMediaOnPromote?: {
|
||||
audio?: boolean;
|
||||
video?: boolean;
|
||||
};
|
||||
hideVisitorCountForVisitors?: boolean;
|
||||
showJoinMeetingDialog?: boolean;
|
||||
};
|
||||
|
||||
// P2P configuration
|
||||
p2p?: {
|
||||
enabled?: boolean;
|
||||
iceTransportPolicy?: 'all' | 'relay';
|
||||
codecPreferenceOrder?: ('AV1' | 'VP9' | 'VP8' | 'H264')[];
|
||||
mobileCodecPreferenceOrder?: ('AV1' | 'VP9' | 'VP8' | 'H264')[];
|
||||
screenshareCodec?: string;
|
||||
mobileScreenshareCodec?: string;
|
||||
backToP2PDelay?: number;
|
||||
stunServers?: Array<{ urls: string }>;
|
||||
};
|
||||
|
||||
// Testing/experimental features
|
||||
testing?: {
|
||||
assumeBandwidth?: boolean;
|
||||
enableAV1ForFF?: boolean;
|
||||
enableCodecSelectionAPI?: boolean;
|
||||
p2pTestMode?: boolean;
|
||||
testMode?: boolean;
|
||||
noAutoPlayVideo?: boolean;
|
||||
skipInterimTranscriptions?: boolean;
|
||||
dumpTranscript?: boolean;
|
||||
debugAudioLevels?: boolean;
|
||||
failICE?: boolean;
|
||||
showSpotConsentDialog?: boolean;
|
||||
};
|
||||
|
||||
// Analytics configuration
|
||||
analytics?: {
|
||||
disabled?: boolean;
|
||||
rtcstatsEnabled?: boolean;
|
||||
rtcstatsStoreLogs?: boolean;
|
||||
rtcstatsEndpoint?: string;
|
||||
rtcstatsPollInterval?: number;
|
||||
rtcstatsSendSdp?: boolean;
|
||||
watchRTCEnabled?: boolean;
|
||||
};
|
||||
|
||||
// Gravatar configuration
|
||||
gravatar?: {
|
||||
baseUrl?: string;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
// Legal URLs
|
||||
legalUrls?: {
|
||||
helpCentre?: string;
|
||||
privacy?: string;
|
||||
terms?: string;
|
||||
};
|
||||
|
||||
// Other settings
|
||||
apiLogLevels?: LogLevel[];
|
||||
mouseMoveCallbackInterval?: number;
|
||||
channelLastN?: number;
|
||||
startLastN?: number;
|
||||
useHostPageLocalStorage?: boolean;
|
||||
disableRtx?: boolean;
|
||||
enableTcc?: boolean;
|
||||
enableRemb?: boolean;
|
||||
enableForcedReload?: boolean;
|
||||
useTurnUdp?: boolean;
|
||||
enableEncodedTransformSupport?: boolean;
|
||||
disableThirdPartyRequests?: boolean;
|
||||
enableCalendarIntegration?: boolean;
|
||||
notifyOnConferenceDestruction?: boolean;
|
||||
feedbackPercentage?: number;
|
||||
roomPasswordNumberOfDigits?: number | false;
|
||||
noticeMessage?: string;
|
||||
enableTalkWhileMuted?: boolean;
|
||||
forceTurnRelay?: boolean;
|
||||
hideLoginButton?: boolean;
|
||||
disableWebrtcStats?: boolean;
|
||||
disableShowMoreStats?: boolean;
|
||||
etherpad_base?: string;
|
||||
openSharedDocumentOnJoin?: boolean;
|
||||
screenshotCapture?: {
|
||||
enabled?: boolean;
|
||||
mode?: 'recording' | 'always';
|
||||
};
|
||||
webrtcIceUdpDisable?: boolean;
|
||||
webrtcIceTcpDisable?: boolean;
|
||||
disableBeforeUnloadHandlers?: boolean;
|
||||
|
||||
// Logging configuration
|
||||
logging?: {
|
||||
defaultLogLevel?: 'trace' | 'debug' | 'info' | 'log' | 'warn' | 'error';
|
||||
disableLogCollector?: boolean;
|
||||
loggers?: Record<string, string>;
|
||||
};
|
||||
|
||||
// File sharing configuration
|
||||
fileSharing?: {
|
||||
apiUrl?: string;
|
||||
enabled?: boolean;
|
||||
maxFileSize?: number;
|
||||
};
|
||||
|
||||
// Dropbox integration
|
||||
dropbox?: {
|
||||
appKey?: string;
|
||||
redirectURI?: string;
|
||||
};
|
||||
|
||||
// Dynamic branding
|
||||
dynamicBrandingUrl?: string;
|
||||
|
||||
// Shared video allowed domains
|
||||
sharedVideoAllowedURLDomains?: string[];
|
||||
|
||||
// CORS avatar URLs
|
||||
corsAvatarURLs?: string[];
|
||||
|
||||
// Recording limit
|
||||
recordingLimit?: {
|
||||
limit?: number;
|
||||
appName?: string;
|
||||
appURL?: string;
|
||||
};
|
||||
|
||||
// Chrome extension banner
|
||||
chromeExtensionBanner?: {
|
||||
url?: string;
|
||||
edgeUrl?: string;
|
||||
chromeExtensionsInfo?: Array<{
|
||||
id: string;
|
||||
path: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
// Allow any additional config options
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Most interfaceConfig options are being migrated to config.js.
|
||||
* Use configOverwrite instead where possible.
|
||||
*/
|
||||
interface InterfaceConfigOverwrite {
|
||||
/** @deprecated Use config.disableModeratorIndicator instead */
|
||||
DISABLE_DOMINANT_SPEAKER_INDICATOR?: boolean;
|
||||
TILE_VIEW_MAX_COLUMNS?: number;
|
||||
SHOW_JITSI_WATERMARK?: boolean;
|
||||
@@ -467,6 +960,7 @@ interface InterfaceConfigOverwrite {
|
||||
SHOW_BRAND_WATERMARK?: boolean;
|
||||
SHOW_POWERED_BY?: boolean;
|
||||
SHOW_PROMOTIONAL_CLOSE_PAGE?: boolean;
|
||||
/** @deprecated Use config.toolbarButtons instead */
|
||||
TOOLBAR_BUTTONS?: ToolbarButton[];
|
||||
SETTINGS_SECTIONS?: SettingsSection[];
|
||||
VIDEO_LAYOUT_FIT?: 'both' | 'width' | 'height';
|
||||
@@ -474,8 +968,44 @@ interface InterfaceConfigOverwrite {
|
||||
FILM_STRIP_MAX_HEIGHT?: number;
|
||||
MOBILE_APP_PROMO?: boolean;
|
||||
HIDE_INVITE_MORE_HEADER?: boolean;
|
||||
/** @deprecated Use config.disabledSounds instead */
|
||||
DISABLE_JOIN_LEAVE_NOTIFICATIONS?: boolean;
|
||||
DISABLE_VIDEO_BACKGROUND?: boolean;
|
||||
DEFAULT_BACKGROUND?: string;
|
||||
DEFAULT_WELCOME_PAGE_LOGO_URL?: string;
|
||||
DEFAULT_LOGO_URL?: string;
|
||||
JITSI_WATERMARK_LINK?: string;
|
||||
BRAND_WATERMARK_LINK?: string;
|
||||
APP_NAME?: string;
|
||||
NATIVE_APP_NAME?: string;
|
||||
PROVIDER_NAME?: string;
|
||||
LANG_DETECTION?: boolean;
|
||||
ENFORCE_NOTIFICATION_AUTO_DISMISS_TIMEOUT?: number;
|
||||
MAXIMUM_ZOOMING_COEFFICIENT?: number;
|
||||
SUPPORT_URL?: string;
|
||||
CONNECTION_INDICATOR_AUTO_HIDE_ENABLED?: boolean;
|
||||
CONNECTION_INDICATOR_AUTO_HIDE_TIMEOUT?: number;
|
||||
CONNECTION_INDICATOR_DISABLED?: boolean;
|
||||
AUTO_PIN_LATEST_SCREEN_SHARE?: string;
|
||||
DISABLE_FOCUS_INDICATOR?: boolean;
|
||||
DISABLE_PRESENCE_STATUS?: boolean;
|
||||
DISABLE_TRANSCRIPTION_SUBTITLES?: boolean;
|
||||
DISABLE_RINGING?: boolean;
|
||||
AUDIO_LEVEL_PRIMARY_COLOR?: string;
|
||||
AUDIO_LEVEL_SECONDARY_COLOR?: string;
|
||||
FILMSTRIP_MAX_HEIGHT?: number;
|
||||
GENERATE_ROOMNAMES_ON_WELCOME_PAGE?: boolean;
|
||||
HIDE_DEEP_LINKING_LOGO?: boolean;
|
||||
INITIAL_TOOLBAR_TIMEOUT?: number;
|
||||
TOOLBAR_TIMEOUT?: number;
|
||||
TOOLBAR_ALWAYS_VISIBLE?: boolean;
|
||||
LOCAL_THUMBNAIL_RATIO?: number;
|
||||
REMOTE_THUMBNAIL_RATIO?: number;
|
||||
LIVE_STREAMING_HELP_LINK?: string;
|
||||
POLICY_LOGO?: string;
|
||||
RECENT_LIST_ENABLED?: boolean;
|
||||
SHOW_CHROME_EXTENSION_BANNER?: boolean;
|
||||
VIDEO_QUALITY_LABEL_DISABLED?: boolean;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
@@ -1278,21 +1808,26 @@ type ToolbarButton =
|
||||
| 'dock-iframe'
|
||||
| 'download'
|
||||
| 'embedmeeting'
|
||||
| 'end-meeting'
|
||||
| 'etherpad'
|
||||
| 'feedback'
|
||||
| 'filmstrip'
|
||||
| 'fullscreen'
|
||||
| 'hangup'
|
||||
| 'hangup-menu'
|
||||
| 'help'
|
||||
| 'highlight'
|
||||
| 'invite'
|
||||
| 'linktosalesforce'
|
||||
| 'livestreaming'
|
||||
| 'microphone'
|
||||
| 'mute-everyone'
|
||||
| 'mute-video-everyone'
|
||||
| 'noisesuppression'
|
||||
| 'participants-pane'
|
||||
| 'profile'
|
||||
| 'raisehand'
|
||||
| 'reactions'
|
||||
| 'recording'
|
||||
| 'security'
|
||||
| 'select-background'
|
||||
|
||||
Reference in New Issue
Block a user