mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-02-07 06:20:18 +00:00
Compare commits
1 Commits
9028
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d32907178 |
14
.github/workflows/ci.yml
vendored
14
.github/workflows/ci.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f #v6.1.0
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 #v6.2.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
os: [macos-latest, ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f #v6.1.0
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 #v6.2.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f #v6.1.0
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 #v6.2.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f #v6.1.0
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 #v6.2.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
rm -rf /host/usr/share/swift
|
||||
df -h /
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f #v6.1.0
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 #v6.2.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -138,7 +138,7 @@ jobs:
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f #v6.1.0
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 #v6.2.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -188,7 +188,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f #v6.1.0
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 #v6.2.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
@@ -927,9 +927,6 @@ var config = {
|
||||
// [ 'microphone', 'camera' ]
|
||||
// ],
|
||||
|
||||
// Enable reduced UI on web.
|
||||
// reducedUIEnabled: true,
|
||||
|
||||
// Overrides the buttons displayed in the main toolbar for reduced UI.
|
||||
// When there isn't an override for a certain configuration the default jitsi-meet configuration will be used.
|
||||
// The order of the buttons in the array is preserved.
|
||||
|
||||
@@ -45,7 +45,7 @@ body {
|
||||
|
||||
.jitsi-icon {
|
||||
&-default svg {
|
||||
fill: var(--icon-default-color, white);
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.always-on-top-toolbox {
|
||||
background-color: var(--toolbox-background-color, $newToolbarBackgroundColor);
|
||||
background-color: $newToolbarBackgroundColor;
|
||||
border-radius: 3px;
|
||||
display: flex;
|
||||
z-index: $toolbarZ;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Round badge.
|
||||
*/
|
||||
.badge-round {
|
||||
background-color: var(--toolbar-badge-background, #165ECC);
|
||||
background-color: #165ECC;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
color: #FFFFFF;
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
.toolbox-content-wrapper::after {
|
||||
content: '';
|
||||
background: var(--toolbox-background-color, $newToolbarBackgroundColor);
|
||||
background: $newToolbarBackgroundColor;
|
||||
padding-bottom: env(safe-area-inset-bottom, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
}
|
||||
|
||||
#notification-participant-list {
|
||||
background-color: var(--toolbox-background-color, $newToolbarBackgroundColor);
|
||||
background-color: $newToolbarBackgroundColor;
|
||||
border: 1px solid rgba(255, 255, 255, .4);
|
||||
border-radius: 8px;
|
||||
left: 0;
|
||||
|
||||
@@ -1407,7 +1407,7 @@ PODS:
|
||||
- Yoga
|
||||
- react-native-performance (5.1.2):
|
||||
- React-Core
|
||||
- react-native-safe-area-context (5.6.1):
|
||||
- react-native-safe-area-context (5.5.2):
|
||||
- React-Core
|
||||
- react-native-slider (4.5.6):
|
||||
- DoubleConversion
|
||||
@@ -2271,7 +2271,7 @@ SPEC CHECKSUMS:
|
||||
react-native-orientation-locker: dbd3f6ddbe9e62389cb0807dc2af63f6c36dec36
|
||||
react-native-pager-view: 11662c698c8f11d39e05891316d2a144fa00adc4
|
||||
react-native-performance: 125a96c145e29918b55b45ce25cbba54f1e24dcd
|
||||
react-native-safe-area-context: 2243039f43d10cb1ea30ec5ac57fc6d1448413f4
|
||||
react-native-safe-area-context: 0f7bf11598f9a61b7ceac8dc3f59ef98697e99e1
|
||||
react-native-slider: 1205801a8d29b28cacc14eef08cb120015cdafcb
|
||||
react-native-video: eb861d67a71dfef1bbf6086a811af5f338b13781
|
||||
react-native-webrtc: e8f0ce746353adc2744a2b933645e1aeb41eaa74
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -227,9 +227,6 @@
|
||||
"video_ssrc": "Video SSRC:",
|
||||
"yes": "yes"
|
||||
},
|
||||
"customPanel": {
|
||||
"close": "Close"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "Earlier",
|
||||
"today": "Today",
|
||||
@@ -1318,7 +1315,6 @@
|
||||
"chat": "Open / Close chat",
|
||||
"clap": "Clap",
|
||||
"closeChat": "Close chat",
|
||||
"closeCustomPanel": "Close",
|
||||
"closeMoreActions": "Close more actions menu",
|
||||
"closeParticipantsPane": "Close participants pane",
|
||||
"closedCaptions": "Closed captions",
|
||||
@@ -1424,11 +1420,9 @@
|
||||
"chat": "Open / Close chat",
|
||||
"clap": "Clap",
|
||||
"closeChat": "Close chat",
|
||||
"closeCustomPanel": "Close",
|
||||
"closeParticipantsPane": "Close participants pane",
|
||||
"closeReactionsMenu": "Close reactions menu",
|
||||
"closedCaptions": "Closed captions",
|
||||
"copilot": "Copilot",
|
||||
"disableNoiseSuppression": "Disable extra noise suppression",
|
||||
"disableReactionSounds": "You can disable reaction sounds for this meeting",
|
||||
"documentClose": "Close shared document",
|
||||
|
||||
@@ -240,28 +240,14 @@ function initCommands() {
|
||||
APP.store.dispatch(muteAllParticipants(exclude, muteMediaType));
|
||||
},
|
||||
'mute-remote-participant': (participantId, mediaType) => {
|
||||
const state = APP.store.getState();
|
||||
const muteMediaType = mediaType ? mediaType : MEDIA_TYPE.AUDIO;
|
||||
const localParticipant = getLocalParticipant(state);
|
||||
|
||||
// Check if targeting the local participant
|
||||
if (participantId === localParticipant?.id) {
|
||||
|
||||
if (muteMediaType === MEDIA_TYPE.AUDIO) {
|
||||
APP.conference.toggleAudioMuted(false);
|
||||
} else if (muteMediaType === MEDIA_TYPE.VIDEO) {
|
||||
APP.conference.toggleVideoMuted(false, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isLocalParticipantModerator(state)) {
|
||||
if (!isLocalParticipantModerator(APP.store.getState())) {
|
||||
logger.error('Missing moderator rights to mute remote participant');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const muteMediaType = mediaType ? mediaType : MEDIA_TYPE.AUDIO;
|
||||
|
||||
APP.store.dispatch(muteRemote(participantId, muteMediaType));
|
||||
},
|
||||
'toggle-lobby': isLobbyEnabled => {
|
||||
@@ -804,7 +790,7 @@ function initCommands() {
|
||||
}
|
||||
|
||||
if (transcription) {
|
||||
APP.store.dispatch(setRequestingSubtitles(true, false, null, true));
|
||||
APP.store.dispatch(setRequestingSubtitles(true, false, null));
|
||||
}
|
||||
},
|
||||
|
||||
@@ -826,7 +812,7 @@ function initCommands() {
|
||||
}
|
||||
|
||||
if (transcription) {
|
||||
APP.store.dispatch(setRequestingSubtitles(false, false, null, true));
|
||||
APP.store.dispatch(setRequestingSubtitles(false, false, null));
|
||||
}
|
||||
|
||||
if (mode === 'local') {
|
||||
@@ -1431,15 +1417,17 @@ class API {
|
||||
*
|
||||
* @param {string} participantId - The ID of the participant.
|
||||
* @param {boolean} isMuted - True if muted, false if unmuted.
|
||||
* @param {string} mediaType - Media type that was muted ('audio' or 'video').
|
||||
* @param {string} mediaType - Media type that was muted ('audio', 'video', or 'desktop').
|
||||
* @param {boolean} isSelfMuted - True if participant muted themselves, false if muted by moderator.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyParticipantMuted(participantId, isMuted, mediaType) {
|
||||
notifyParticipantMuted(participantId, isMuted, mediaType, isSelfMuted = true) {
|
||||
this._sendEvent({
|
||||
name: 'participant-muted',
|
||||
id: participantId,
|
||||
isMuted,
|
||||
mediaType
|
||||
mediaType,
|
||||
isSelfMuted
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
2133
package-lock.json
generated
2133
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@@ -72,7 +72,7 @@
|
||||
"js-md5": "0.6.1",
|
||||
"js-sha512": "0.8.0",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v2124.0.0+80df84a1/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v2118.0.0+67fd2c84/lib-jitsi-meet.tgz",
|
||||
"lodash-es": "4.17.21",
|
||||
"null-loader": "4.0.1",
|
||||
"optional-require": "1.0.3",
|
||||
@@ -97,7 +97,7 @@
|
||||
"react-native-pager-view": "6.8.1",
|
||||
"react-native-paper": "5.10.3",
|
||||
"react-native-performance": "5.1.2",
|
||||
"react-native-safe-area-context": "5.6.1",
|
||||
"react-native-safe-area-context": "5.5.2",
|
||||
"react-native-screens": "4.11.1",
|
||||
"react-native-sound": "https://github.com/jitsi/react-native-sound.git#ea13c97b5c2a4ff5e0d9bacbd9ff5e4457fe2c3c",
|
||||
"react-native-splash-view": "0.0.18",
|
||||
@@ -164,12 +164,12 @@
|
||||
"@types/w3c-image-capture": "1.0.6",
|
||||
"@types/w3c-web-hid": "1.0.3",
|
||||
"@types/zxcvbn": "4.4.1",
|
||||
"@wdio/allure-reporter": "9.23.2",
|
||||
"@wdio/cli": "9.23.2",
|
||||
"@wdio/globals": "9.23.0",
|
||||
"@wdio/junit-reporter": "9.23.2",
|
||||
"@wdio/local-runner": "9.23.2",
|
||||
"@wdio/mocha-framework": "9.23.2",
|
||||
"@wdio/allure-reporter": "9.22.0",
|
||||
"@wdio/cli": "9.22.0",
|
||||
"@wdio/globals": "9.17.0",
|
||||
"@wdio/junit-reporter": "9.21.0",
|
||||
"@wdio/local-runner": "9.22.0",
|
||||
"@wdio/mocha-framework": "9.22.0",
|
||||
"babel-loader": "9.1.0",
|
||||
"babel-plugin-optional-require": "0.3.1",
|
||||
"circular-dependency-plugin": "5.2.0",
|
||||
@@ -194,7 +194,7 @@
|
||||
"typescript": "5.7.2",
|
||||
"unorm": "1.6.0",
|
||||
"webdriverio": "9.22.0",
|
||||
"webpack": "5.105.0",
|
||||
"webpack": "5.95.0",
|
||||
"webpack-bundle-analyzer": "4.4.2",
|
||||
"webpack-cli": "5.1.4",
|
||||
"webpack-dev-server": "5.1.0"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { setRoom } from '../base/conference/actions.native';
|
||||
import { setRoom } from '../base/conference/actions';
|
||||
import { getConferenceState } from '../base/conference/functions';
|
||||
import {
|
||||
configWillLoad,
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
} from '../mobile/navigation/rootNavigationContainerRef';
|
||||
import { screen } from '../mobile/navigation/routes';
|
||||
import { clearNotifications } from '../notifications/actions';
|
||||
import { isUnsafeRoomWarningEnabled } from '../prejoin/functions.native';
|
||||
import { isUnsafeRoomWarningEnabled } from '../prejoin/functions';
|
||||
|
||||
import { maybeRedirectToTokenAuthUrl } from './actions.any';
|
||||
import { addTrackStateToURL, getDefaultURL } from './functions.native';
|
||||
|
||||
@@ -26,6 +26,5 @@ import '../face-landmarks/middleware';
|
||||
import '../gifs/middleware';
|
||||
import '../whiteboard/middleware.web';
|
||||
import '../file-sharing/middleware.web';
|
||||
import '../custom-panel/middleware.web';
|
||||
|
||||
import './middlewares.any';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import '../base/devices/reducer';
|
||||
import '../base/premeeting/reducer';
|
||||
import '../custom-panel/reducer';
|
||||
import '../base/tooltip/reducer';
|
||||
import '../e2ee/reducer';
|
||||
import '../face-landmarks/reducer';
|
||||
|
||||
@@ -31,7 +31,6 @@ import { IUserInteractionState } from '../base/user-interaction/reducer';
|
||||
import { IBreakoutRoomsState } from '../breakout-rooms/reducer';
|
||||
import { ICalendarSyncState } from '../calendar-sync/reducer';
|
||||
import { IChatState } from '../chat/reducer';
|
||||
import { ICustomPanelState } from '../custom-panel/reducer';
|
||||
import { IDeepLinkingState } from '../deep-linking/reducer';
|
||||
import { IDropboxState } from '../dropbox/reducer';
|
||||
import { IDynamicBrandingState } from '../dynamic-branding/reducer';
|
||||
@@ -122,7 +121,6 @@ export interface IReduxState {
|
||||
'features/calendar-sync': ICalendarSyncState;
|
||||
'features/call-integration': ICallIntegrationState;
|
||||
'features/chat': IChatState;
|
||||
'features/custom-panel': ICustomPanelState;
|
||||
'features/deep-linking': IDeepLinkingState;
|
||||
'features/dropbox': IDropboxState;
|
||||
'features/dynamic-branding': IDynamicBrandingState;
|
||||
|
||||
@@ -81,6 +81,7 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
|
||||
break;
|
||||
}
|
||||
case LOCAL_PARTICIPANT_MODERATION_NOTIFICATION: {
|
||||
let descriptionKey;
|
||||
let titleKey;
|
||||
let uid = '';
|
||||
const localParticipant = getLocalParticipant(getState);
|
||||
@@ -110,6 +111,8 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
|
||||
!raisedHand && dispatch(raiseHand(true));
|
||||
dispatch(hideNotification(uid));
|
||||
}) ],
|
||||
descriptionKey,
|
||||
sticky: true,
|
||||
titleKey,
|
||||
uid
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
|
||||
@@ -268,6 +271,7 @@ StateListenerRegistry.register(
|
||||
|
||||
dispatch(showNotification({
|
||||
titleKey: 'notify.hostAskedUnmute',
|
||||
sticky: true,
|
||||
customActionNameKey,
|
||||
customActionHandler,
|
||||
uid: ASKED_TO_UNMUTE_NOTIFICATION_ID
|
||||
|
||||
@@ -93,17 +93,10 @@ export function commonUserJoinedHandling(
|
||||
if (!user.isHidden()) {
|
||||
const isReplacing = user?.isReplacing();
|
||||
const isPromoted = conference?.getMetadataHandler().getMetadata()?.visitors?.promoted?.[id];
|
||||
const userIdentity = user.getIdentity()?.user;
|
||||
|
||||
// Map identity from JWT context to userContext for external API
|
||||
const userContext = userIdentity ? {
|
||||
id: userIdentity.id,
|
||||
name: userIdentity.name
|
||||
} : undefined;
|
||||
|
||||
// the identity and avatar come from jwt and never change in the presence
|
||||
dispatch(participantJoined({
|
||||
avatarURL: userIdentity?.avatar,
|
||||
avatarURL: user.getIdentity()?.user?.avatar,
|
||||
botType: user.getBotType(),
|
||||
conference,
|
||||
id,
|
||||
@@ -112,8 +105,7 @@ export function commonUserJoinedHandling(
|
||||
role: user.getRole(),
|
||||
isPromoted,
|
||||
isReplacing,
|
||||
sources: user.getSources(),
|
||||
userContext
|
||||
sources: user.getSources()
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,7 +559,6 @@ export interface IConfig {
|
||||
skipConsentInMeeting?: boolean;
|
||||
suggestRecording?: boolean;
|
||||
};
|
||||
reducedUIEnabled?: boolean;
|
||||
reducedUImainToolbarButtons?: Array<string>;
|
||||
remoteVideoMenu?: {
|
||||
disableDemote?: boolean;
|
||||
|
||||
@@ -215,7 +215,6 @@ export default [
|
||||
'recordings.showPrejoinWarning',
|
||||
'recordings.showRecordingLink',
|
||||
'recordings.suggestRecording',
|
||||
'reducedUIEnabled',
|
||||
'reducedUImainToolbarButtons',
|
||||
'replaceParticipant',
|
||||
'resolution',
|
||||
|
||||
@@ -387,8 +387,7 @@ export function setConfigFromURLParams(
|
||||
|
||||
// When not in an iframe, start without media if the pre-join page is not enabled.
|
||||
if (!isEmbedded()
|
||||
&& ('config.prejoinConfig' in params || 'config.prejoinConfig.enabled' in params)
|
||||
&& config.prejoinConfig?.enabled === false) {
|
||||
&& 'config.prejoinConfig.enabled' in params && config.prejoinConfig?.enabled === false) {
|
||||
logger.warn('Using prejoinConfig.enabled config URL overwrite implies starting without media.');
|
||||
config.disableInitialGUM = true;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { getCustomerDetails } from '../../jaas/actions.any';
|
||||
import { getJaasJWT, isVpaasMeeting } from '../../jaas/functions';
|
||||
import { navigateRoot } from '../../mobile/navigation/rootNavigationContainerRef';
|
||||
import { screen } from '../../mobile/navigation/routes';
|
||||
import { conferenceWillLeave } from '../conference/actions.native';
|
||||
import { setJWT } from '../jwt/actions';
|
||||
import { JitsiConnectionErrors } from '../lib-jitsi-meet';
|
||||
|
||||
@@ -59,8 +58,5 @@ export function connect(id?: string, password?: string) {
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function hangup(_requestFeedback = false) {
|
||||
return (dispatch: IStore['dispatch']) => {
|
||||
dispatch(conferenceWillLeave());
|
||||
dispatch(appNavigate(undefined));
|
||||
};
|
||||
return (dispatch: IStore['dispatch']) => dispatch(appNavigate(undefined));
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export * from './utils.any';
|
||||
@@ -29,3 +29,4 @@ export function isIpadMobileBrowser() {
|
||||
// @ts-ignore
|
||||
return isIosMobileBrowser() && Platform.isPad;
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import { MIN_FILMSTRIP_RESIZE_WIDTH } from '../../filmstrip/constants';
|
||||
|
||||
/**
|
||||
* Detects if the current device has touch capability.
|
||||
* This includes smartphones, tablets, and laptops with touch screens.
|
||||
*
|
||||
* @returns {boolean} True if the device supports touch events.
|
||||
*/
|
||||
export function isTouchDevice(): boolean {
|
||||
// Check maxTouchPoints (most reliable for modern browsers)
|
||||
if ('maxTouchPoints' in navigator) {
|
||||
return navigator.maxTouchPoints > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if resize functionality should be enabled based on device capabilities
|
||||
* and screen size. On touch devices, resize is only enabled for larger screens.
|
||||
* On non-touch devices (desktop), resize is always enabled.
|
||||
*
|
||||
* @returns {boolean} True if resize functionality should be available to the user.
|
||||
*/
|
||||
export function shouldEnableResize(): boolean {
|
||||
const hasTouch = isTouchDevice();
|
||||
|
||||
// On non-touch devices (desktop), always enable resize
|
||||
if (!hasTouch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// On touch devices, only enable if screen is large enough.
|
||||
return window?.innerWidth >= MIN_FILMSTRIP_RESIZE_WIDTH;
|
||||
}
|
||||
|
||||
export * from './utils.any';
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles-icon lucide-sparkles"><path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"/><path d="M20 2v4"/><path d="M22 4h-4"/><circle cx="4" cy="20" r="2"/></svg>
|
||||
|
Before Width: | Height: | Size: 582 B |
@@ -1,4 +1,3 @@
|
||||
import { default as IconAI } from './AI.svg';
|
||||
import { default as IconRecordAccount } from './account-record.svg';
|
||||
import { default as IconAddUser } from './add-user.svg';
|
||||
import { default as IconArrowBack } from './arrow-back.svg';
|
||||
@@ -113,7 +112,6 @@ import { default as IconYahoo } from './yahoo.svg';
|
||||
*/
|
||||
export const DEFAULT_ICON: Record<string, any> = {
|
||||
IconAddUser,
|
||||
IconAI,
|
||||
IconArrowBack,
|
||||
IconArrowDown,
|
||||
IconArrowDownLarge,
|
||||
|
||||
@@ -4,7 +4,6 @@ import { DEFAULT_ICON } from './constants';
|
||||
|
||||
const {
|
||||
IconAddUser,
|
||||
IconAI,
|
||||
IconArrowBack,
|
||||
IconArrowDown,
|
||||
IconArrowDownLarge,
|
||||
@@ -124,7 +123,6 @@ const {
|
||||
|
||||
export {
|
||||
IconAddUser,
|
||||
IconAI,
|
||||
IconArrowBack,
|
||||
IconArrowDown,
|
||||
IconArrowDownLarge,
|
||||
|
||||
@@ -56,9 +56,9 @@ const useStyles = makeStyles()(theme => {
|
||||
label: {
|
||||
...theme.typography.labelRegular,
|
||||
alignItems: 'center',
|
||||
background: theme.palette.labelBackground,
|
||||
background: theme.palette.ui04,
|
||||
borderRadius: '4px',
|
||||
color: theme.palette.labelText,
|
||||
color: theme.palette.text01,
|
||||
display: 'flex',
|
||||
margin: '0 2px',
|
||||
padding: '6px',
|
||||
@@ -72,11 +72,11 @@ const useStyles = makeStyles()(theme => {
|
||||
cursor: 'pointer'
|
||||
},
|
||||
[COLORS.white]: {
|
||||
background: theme.palette.labelWhiteBackground,
|
||||
color: theme.palette.labelWhiteText,
|
||||
background: theme.palette.ui09,
|
||||
color: theme.palette.text04,
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.labelWhiteIcon
|
||||
fill: theme.palette.icon04
|
||||
}
|
||||
},
|
||||
[COLORS.green]: {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { IReduxState, IStore } from '../../app/types';
|
||||
import { getLocalParticipant } from '../participants/functions';
|
||||
import StateListenerRegistry from '../redux/StateListenerRegistry';
|
||||
|
||||
/**
|
||||
@@ -14,13 +13,6 @@ StateListenerRegistry.register(
|
||||
|
||||
if (muted !== previousMuted) {
|
||||
APP.API.notifyAudioMutedStatusChanged(muted);
|
||||
|
||||
// Also fire the participantMuted event for consistency
|
||||
const localParticipant = getLocalParticipant(store.getState());
|
||||
|
||||
if (localParticipant) {
|
||||
APP.API.notifyParticipantMuted(localParticipant.id, muted, 'audio');
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -17,7 +17,7 @@ interface IProps {
|
||||
/**
|
||||
* The children component(s) of the Modal, to be rendered.
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Additional style to be appended to the KeyboardAvoidingView content container.
|
||||
@@ -63,7 +63,7 @@ const JitsiScreen = ({
|
||||
footerComponent,
|
||||
hasBottomTextInput = false,
|
||||
hasExtraHeaderHeight = false,
|
||||
safeAreaInsets = [ 'bottom', 'left', 'right' ],
|
||||
safeAreaInsets = [ 'left', 'right' ],
|
||||
style
|
||||
}: IProps) => {
|
||||
const renderContent = () => (
|
||||
@@ -78,8 +78,8 @@ const JitsiScreen = ({
|
||||
edges = { safeAreaInsets }
|
||||
style = { styles.safeArea }>
|
||||
{ children }
|
||||
{ footerComponent?.() }
|
||||
</SafeAreaView>
|
||||
{ footerComponent?.() }
|
||||
</JitsiKeyboardAvoidingView>
|
||||
);
|
||||
|
||||
|
||||
@@ -606,21 +606,13 @@ function _e2eeUpdated({ getState, dispatch }: IStore, conference: IJitsiConferen
|
||||
function _localParticipantJoined({ getState, dispatch }: IStore, next: Function, action: AnyAction) {
|
||||
const result = next(action);
|
||||
|
||||
const state = getState();
|
||||
const settings = state['features/base/settings'];
|
||||
const jwtUser = state['features/base/jwt']?.user;
|
||||
|
||||
const userContext = jwtUser ? {
|
||||
id: jwtUser.id,
|
||||
name: jwtUser.name
|
||||
} : undefined;
|
||||
const settings = getState()['features/base/settings'];
|
||||
|
||||
dispatch(localParticipantJoined({
|
||||
avatarURL: settings.avatarURL,
|
||||
email: settings.email,
|
||||
name: settings.displayName,
|
||||
id: '',
|
||||
userContext
|
||||
id: ''
|
||||
}));
|
||||
|
||||
return result;
|
||||
|
||||
@@ -627,8 +627,7 @@ function _participantJoined({ participant }: { participant: IParticipant; }) {
|
||||
pinned,
|
||||
presence,
|
||||
role,
|
||||
sources,
|
||||
userContext
|
||||
sources
|
||||
} = participant;
|
||||
let { conference, id } = participant;
|
||||
|
||||
@@ -660,8 +659,7 @@ function _participantJoined({ participant }: { participant: IParticipant; }) {
|
||||
pinned: pinned || false,
|
||||
presence,
|
||||
role: role || PARTICIPANT_ROLE.NONE,
|
||||
sources,
|
||||
userContext
|
||||
sources
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -41,12 +41,6 @@ export interface IParticipant {
|
||||
role?: string;
|
||||
sources?: Map<string, Map<string, ISourceInfo>>;
|
||||
supportsRemoteControl?: boolean;
|
||||
userContext?: IUserContext;
|
||||
}
|
||||
|
||||
export interface IUserContext {
|
||||
id?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface ILocalParticipant extends IParticipant {
|
||||
|
||||
@@ -84,7 +84,7 @@ const useStyles = makeStyles()(theme => {
|
||||
...theme.typography.bodyLongBold,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
boxSizing: 'border-box',
|
||||
color: theme.palette.actionButtonText,
|
||||
color: theme.palette.text01,
|
||||
cursor: 'pointer',
|
||||
display: 'inline-block',
|
||||
marginBottom: '16px',
|
||||
@@ -95,20 +95,20 @@ const useStyles = makeStyles()(theme => {
|
||||
border: 0,
|
||||
|
||||
'&.primary': {
|
||||
background: theme.palette.prejoinActionButtonPrimary,
|
||||
color: theme.palette.prejoinActionButtonPrimaryText,
|
||||
background: theme.palette.action01,
|
||||
color: theme.palette.text01,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.prejoinActionButtonPrimaryHover
|
||||
backgroundColor: theme.palette.action01Hover
|
||||
}
|
||||
},
|
||||
|
||||
'&.secondary': {
|
||||
background: theme.palette.prejoinActionButtonSecondary,
|
||||
color: theme.palette.prejoinActionButtonSecondaryText,
|
||||
background: theme.palette.action02,
|
||||
color: theme.palette.text04,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.prejoinActionButtonSecondaryHover
|
||||
backgroundColor: theme.palette.action02Hover
|
||||
}
|
||||
},
|
||||
|
||||
@@ -120,7 +120,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&.disabled': {
|
||||
background: theme.palette.prejoinActionButtonDisabled,
|
||||
background: theme.palette.disabled01,
|
||||
border: '1px solid #5E6D7A',
|
||||
color: '#AFB6BC',
|
||||
cursor: 'initial',
|
||||
|
||||
@@ -109,7 +109,7 @@ const useStyles = makeStyles()(theme => {
|
||||
position: 'absolute',
|
||||
inset: '0 0 0 0',
|
||||
display: 'flex',
|
||||
backgroundColor: theme.palette.preMeetingBackground,
|
||||
backgroundColor: theme.palette.ui01,
|
||||
zIndex: 252,
|
||||
|
||||
'@media (max-width: 720px)': {
|
||||
@@ -163,7 +163,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
title: {
|
||||
...theme.typography.heading4,
|
||||
color: theme.palette.prejoinTitleText,
|
||||
color: `${theme.palette.text01}!important`,
|
||||
marginBottom: theme.spacing(3),
|
||||
textAlign: 'center',
|
||||
|
||||
@@ -179,7 +179,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
roomName: {
|
||||
...theme.typography.heading5,
|
||||
color: theme.palette.prejoinRoomNameText,
|
||||
color: theme.palette.text01,
|
||||
display: 'inline-block',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
|
||||
@@ -6,7 +6,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
warning: {
|
||||
bottom: 0,
|
||||
color: theme.palette.prejoinRecordingWarningText,
|
||||
color: theme.palette.text03,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
...theme.typography.bodyShortRegular,
|
||||
|
||||
@@ -11,8 +11,8 @@ import { setUnsafeRoomConsent } from '../../actions.web';
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
warning: {
|
||||
backgroundColor: theme.palette.prejoinWarningBackground,
|
||||
color: theme.palette.prejoinWarningText,
|
||||
backgroundColor: theme.palette.warning01,
|
||||
color: theme.palette.text04,
|
||||
...theme.typography.bodyShortRegular,
|
||||
padding: theme.spacing(3),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
|
||||
@@ -9,11 +9,11 @@ import { getSupportUrl } from '../../functions';
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
dialog: {
|
||||
backgroundColor: theme.palette.dialogBackground,
|
||||
border: `1px solid ${theme.palette.inlineDialogBorder}`,
|
||||
backgroundColor: theme.palette.ui01,
|
||||
border: `1px solid ${theme.palette.ui04}`,
|
||||
borderRadius: `${Number(theme.shape.borderRadius)}px`,
|
||||
boxShadow: '0px 1px 2px rgba(41, 41, 41, 0.25)',
|
||||
color: theme.palette.dialogText,
|
||||
color: theme.palette.text01,
|
||||
...theme.typography.bodyShortRegular,
|
||||
padding: `${theme.spacing(3)} 10`,
|
||||
'& .retry-button': {
|
||||
|
||||
@@ -2,7 +2,6 @@ import { batch } from 'react-redux';
|
||||
|
||||
import { IStore } from '../../app/types';
|
||||
import { CHAT_SIZE } from '../../chat/constants';
|
||||
import { getCustomPanelWidth } from '../../custom-panel/functions';
|
||||
import { getParticipantsPaneWidth } from '../../participants-pane/functions';
|
||||
|
||||
import {
|
||||
@@ -44,7 +43,6 @@ export function clientResized(clientWidth: number, clientHeight: number) {
|
||||
|
||||
if (navigator.product !== 'ReactNative') {
|
||||
const state = getState();
|
||||
const { reducedUIEnabled = true } = state['features/base/config'];
|
||||
const { isOpen: isChatOpen, width } = state['features/chat'];
|
||||
|
||||
if (isChatOpen) {
|
||||
@@ -52,9 +50,8 @@ export function clientResized(clientWidth: number, clientHeight: number) {
|
||||
}
|
||||
|
||||
availableWidth -= getParticipantsPaneWidth(state);
|
||||
availableWidth -= getCustomPanelWidth(state);
|
||||
|
||||
reducedUIEnabled && dispatch(setReducedUI(availableWidth, clientHeight));
|
||||
dispatch(setReducedUI(availableWidth, clientHeight));
|
||||
}
|
||||
|
||||
batch(() => {
|
||||
@@ -115,7 +112,7 @@ export function setReducedUI(width: number, height: number) {
|
||||
const threshold = navigator.product === 'ReactNative'
|
||||
? REDUCED_UI_THRESHOLD
|
||||
: WEB_REDUCED_UI_THRESHOLD;
|
||||
const reducedUI = Math.max(width, height) < threshold;
|
||||
const reducedUI = Math.min(width, height) < threshold;
|
||||
|
||||
if (reducedUI !== getState()['features/base/responsive-ui'].reducedUI) {
|
||||
return dispatch({
|
||||
|
||||
@@ -22,11 +22,11 @@ interface IProps {
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
container: {
|
||||
backgroundColor: theme.palette.tooltipBackground,
|
||||
backgroundColor: theme.palette.uiBackground,
|
||||
borderRadius: '3px',
|
||||
padding: theme.spacing(2),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.tooltipText,
|
||||
color: theme.palette.text01,
|
||||
position: 'relative',
|
||||
|
||||
'&.mounting-animation': {
|
||||
|
||||
@@ -51,7 +51,7 @@ import './subscriber.web';
|
||||
MiddlewareRegistry.register(store => next => action => {
|
||||
switch (action.type) {
|
||||
case TRACK_ADDED: {
|
||||
const { local, jitsiTrack } = action.track;
|
||||
const { local } = action.track;
|
||||
|
||||
// The devices list needs to be refreshed when no initial video permissions
|
||||
// were granted and a local video track is added by umuting the video.
|
||||
@@ -65,16 +65,6 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
|
||||
if (participantId) {
|
||||
logTracksForParticipant(store.getState()['features/base/tracks'], participantId, 'Track added');
|
||||
|
||||
// Fire participantMuted event for initial state of remote tracks
|
||||
if (typeof action.track?.muted !== 'undefined' && jitsiTrack) {
|
||||
const isVideoTrack = jitsiTrack.getType() !== MEDIA_TYPE.AUDIO;
|
||||
const mediaType = isVideoTrack
|
||||
? (jitsiTrack.getVideoType() === VIDEO_TYPE.DESKTOP ? 'desktop' : 'video')
|
||||
: 'audio';
|
||||
|
||||
APP.API.notifyParticipantMuted(participantId, action.track.muted, mediaType);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -129,16 +119,6 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
// TODO Remove the following calls to APP.UI once components interested
|
||||
// in track mute changes are moved into React and/or redux.
|
||||
|
||||
const { jitsiTrack } = action.track;
|
||||
const participantID = jitsiTrack.getParticipantId();
|
||||
const isVideoTrack = jitsiTrack.type !== MEDIA_TYPE.AUDIO;
|
||||
const local = jitsiTrack.isLocal();
|
||||
|
||||
// Get old muted state BEFORE updating
|
||||
const tracks = store.getState()['features/base/tracks'];
|
||||
const oldTrack = tracks.find((t: ITrack) => t.jitsiTrack === jitsiTrack);
|
||||
const oldMutedState = oldTrack?.muted;
|
||||
|
||||
const result = next(action);
|
||||
const state = store.getState();
|
||||
|
||||
@@ -146,6 +126,11 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
return result;
|
||||
}
|
||||
|
||||
const { jitsiTrack } = action.track;
|
||||
const participantID = jitsiTrack.getParticipantId();
|
||||
const isVideoTrack = jitsiTrack.type !== MEDIA_TYPE.AUDIO;
|
||||
const local = jitsiTrack.isLocal();
|
||||
|
||||
if (isVideoTrack) {
|
||||
if (local && !(jitsiTrack.getVideoType() === VIDEO_TYPE.DESKTOP)) {
|
||||
APP.conference.setVideoMuteStatus();
|
||||
@@ -159,14 +144,12 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
if (typeof action.track?.muted !== 'undefined' && participantID && !local) {
|
||||
logTracksForParticipant(store.getState()['features/base/tracks'], participantID, 'Track updated');
|
||||
|
||||
// Fire participantMuted event only if muted state actually changed
|
||||
if (oldMutedState !== action.track.muted) {
|
||||
const mediaType = isVideoTrack
|
||||
? (jitsiTrack.getVideoType() === VIDEO_TYPE.DESKTOP ? 'desktop' : 'video')
|
||||
: 'audio';
|
||||
// Notify external API when remote participant mutes/unmutes themselves
|
||||
const mediaType = isVideoTrack
|
||||
? (jitsiTrack.getVideoType() === VIDEO_TYPE.DESKTOP ? 'desktop' : 'video')
|
||||
: 'audio';
|
||||
|
||||
APP.API.notifyParticipantMuted(participantID, action.track.muted, mediaType);
|
||||
}
|
||||
APP.API.notifyParticipantMuted(participantID, action.track.muted, mediaType, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { isEqual, sortBy } from 'lodash-es';
|
||||
import VideoLayout from '../../../../modules/UI/videolayout/VideoLayout';
|
||||
import { getAutoPinSetting } from '../../video-layout/functions.any';
|
||||
import { MEDIA_TYPE } from '../media/constants';
|
||||
import { getLocalParticipant, getScreenshareParticipantIds } from '../participants/functions';
|
||||
import { getScreenshareParticipantIds } from '../participants/functions';
|
||||
import StateListenerRegistry from '../redux/StateListenerRegistry';
|
||||
|
||||
import { isLocalTrackMuted } from './functions';
|
||||
@@ -47,13 +47,6 @@ StateListenerRegistry.register(
|
||||
/* listener */ (muted, store, previousMuted) => {
|
||||
if (muted !== previousMuted) {
|
||||
APP.API.notifyVideoMutedStatusChanged(muted);
|
||||
|
||||
// Also fire the participantMuted event for consistency
|
||||
const localParticipant = getLocalParticipant(store.getState());
|
||||
|
||||
if (localParticipant) {
|
||||
APP.API.notifyParticipantMuted(localParticipant.id, muted, 'video');
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @stylistic/no-multi-spaces */
|
||||
// Mapping between the token used and the color
|
||||
export const colorMap = {
|
||||
// ----- Surfaces -----
|
||||
@@ -8,7 +7,7 @@ export const colorMap = {
|
||||
// - JitsiMeetView.java
|
||||
uiBackground: 'surface01',
|
||||
|
||||
// Container backgrounds (legacy tokens)
|
||||
// Container backgrounds
|
||||
ui01: 'surface02',
|
||||
ui02: 'surface03',
|
||||
ui03: 'ui02',
|
||||
@@ -48,426 +47,6 @@ export const colorMap = {
|
||||
// Focus
|
||||
focus01: 'focus01',
|
||||
|
||||
// ----- Semantic Tokens (component-based, backwards compatible) -----
|
||||
|
||||
// Dialog/Modal Components
|
||||
dialogBackground: 'surface02', // Main dialog background (same as ui01)
|
||||
dialogOverlay: 'surface03', // Overlay/backdrop (same as ui02)
|
||||
dialogBorder: 'ui02', // Dialog borders
|
||||
dialogText: 'textColor01', // Primary dialog text (same as text01)
|
||||
dialogSecondaryText: 'textColor02', // Secondary dialog text (same as text02)
|
||||
|
||||
// Large Video
|
||||
largeVideoBackground: 'surface03', // Main video area background (same as ui02)
|
||||
largeVideoPlaceholder: 'surface03', // Placeholder when no video (same as ui02)
|
||||
|
||||
// Filmstrip
|
||||
filmstripBackground: 'surface03', // Filmstrip container background (same as ui02)
|
||||
filmstripBackgroundHover: 'uiBackground', // Filmstrip background on hover/focus
|
||||
filmstripDragHandle: 'icon02', // Filmstrip resize drag handle color
|
||||
filmstripDragHandleHover: 'icon01', // Filmstrip resize drag handle hover color
|
||||
thumbnailBackground: 'surface03', // Individual thumbnail background (same as ui02)
|
||||
thumbnailBorder: 'ui03', // Thumbnail borders (same as ui03)
|
||||
thumbnailHover: 'hover05', // Thumbnail hover state (same as action03Hover)
|
||||
thumbnailTintBackground: 'uiBackground', // Thumbnail tint overlay background
|
||||
thumbnailRaisedHandIcon: 'uiBackground', // Thumbnail raised hand indicator icon
|
||||
thumbnailVideoBackground: 'uiBackground', // Thumbnail video/placeholder background
|
||||
|
||||
// Chat
|
||||
chatBackground: 'surface02', // Chat panel background (same as ui01)
|
||||
chatBackdrop: 'ui04', // Chat screen background (same as ui10)
|
||||
chatEmptyText: 'ui03', // Empty component text
|
||||
chatInputBackground: 'surface03', // Chat input field background (same as ui02)
|
||||
chatInputBorder: 'surface03', // Chat input border (same as ui02)
|
||||
chatLink: 'action01', // Chat link color (same as link01)
|
||||
chatLobbyMessageBubble: 'support06', // Lobby message bubble background
|
||||
chatLobbyMessageNotice: 'surface01', // Lobby message notice text
|
||||
chatLobbyRecipientContainer: 'support06', // Lobby recipient container background
|
||||
chatMessageLocal: 'surface05', // Local participant message bubble (same as ui04)
|
||||
chatMessagePrivate: 'support05', // Private/DM message bubble
|
||||
chatMessageRemote: 'surface03', // Remote participant message bubble (same as ui02)
|
||||
chatMessageText: 'textColor01', // Chat message text
|
||||
chatPrivateNotice: 'textColor02', // Private message notice text
|
||||
chatRecipientCancelIcon: 'icon01', // Recipient cancel icon color
|
||||
chatRecipientContainer: 'support05', // Recipient container background
|
||||
chatRecipientText: 'textColor01', // Recipient text color
|
||||
chatReplyIcon: 'icon01', // Reply icon color
|
||||
chatSenderName: 'textColor02', // Sender display name color
|
||||
chatTimestamp: 'ui03', // Chat timestamp text
|
||||
|
||||
// Toolbox/Toolbar
|
||||
toolboxBackground: 'surface02', // Main toolbox background
|
||||
drawerBackground: 'surface02', // Drawer/side panel background
|
||||
toolboxIconHover: 'surface05', // Toolbox icon hover background
|
||||
toolboxIconActive: 'ui02', // Toolbox icon active/pressed background
|
||||
toolboxIconToggled: 'ui02', // Toolbox icon toggled background
|
||||
toolbarButton: 'action01', // Toolbar button color
|
||||
toolbarButtonHover: 'hover01', // Toolbar button hover (same as action01Hover)
|
||||
toolbarButtonActive: 'active01', // Toolbar button active/pressed state
|
||||
toolbarIcon: 'icon01', // Toolbar icon color
|
||||
toolbarIconHover: 'icon01', // Toolbar icon hover state
|
||||
toolbarIconActive: 'action01', // Toolbar icon active/toggled state
|
||||
|
||||
// Overflow Menu (More Actions)
|
||||
overflowMenuBackground: 'surface02', // Overflow menu background
|
||||
overflowMenuBorder: 'surface05', // Overflow menu border
|
||||
overflowMenuItemText: 'text01', // Overflow menu item text
|
||||
overflowMenuItemIcon: 'text01', // Overflow menu item icon
|
||||
overflowMenuItemHover: 'surface03', // Overflow menu item hover background
|
||||
overflowMenuItemDisabled: 'text03', // Overflow menu item disabled text/icon
|
||||
overflowMenuSeparator: 'ui03', // Overflow menu group separator
|
||||
|
||||
// Participants Pane
|
||||
participantsPaneBackground: 'surface02', // Participants list background
|
||||
participantItemBackground: 'surface03', // Individual participant item background
|
||||
participantItemHover: 'hover05', // Participant item hover
|
||||
participantItemBorder: 'ui02', // Participant item border
|
||||
participantCounterBadge: 'ui02', // Participant counter badge background
|
||||
participantCounterText: 'text01', // Participant counter text
|
||||
participantModeratorLabel: 'text03', // Moderator label text
|
||||
participantSectionText: 'text02', // Section header/subtitle text
|
||||
participantActionButton: 'action02', // Action button background
|
||||
participantLinkText: 'link01', // Link text color
|
||||
participantWarningText: 'warning02', // Warning text color
|
||||
participantRaisedHandBadge: 'warning02', // Raised hand indicator background
|
||||
participantRaisedHandIcon: 'icon04', // Raised hand icon color
|
||||
|
||||
// Lobby
|
||||
lobbyBackground: 'surface02', // Lobby screen background (same as ui01)
|
||||
lobbyPreviewBackground: 'surface03', // Video preview background (same as ui02)
|
||||
|
||||
// Speaker Stats
|
||||
speakerStatsBackground: 'surface02', // Speaker stats panel background
|
||||
speakerStatsRowBackground: 'ui02', // Individual stat row background
|
||||
speakerStatsRowAlternate: 'ui03', // Alternate row background
|
||||
speakerStatsBorder: 'surface03', // Speaker stats borders
|
||||
speakerStatsHeaderBackground: 'ui09', // Header background
|
||||
speakerStatsSearchBackground: 'field01', // Search input background
|
||||
speakerStatsSearchBorder: 'ui05', // Search input border
|
||||
speakerStatsSearchText: 'text01', // Search input text
|
||||
speakerStatsSearchPlaceholder: 'text03', // Search placeholder
|
||||
speakerStatsSearchIcon: 'icon03', // Search icon color
|
||||
speakerStatsLabelText: 'text03', // Label text color
|
||||
speakerStatsSuccessBar: 'success02', // Success/progress bar
|
||||
speakerStatsAvatarLeft: 'surface05', // Avatar background for participants who left
|
||||
|
||||
// Pre-meeting/Prejoin
|
||||
preMeetingBackground: 'surface02', // Pre-meeting screen container background
|
||||
preMeetingPreview: 'ui01', // Video preview in pre-meeting
|
||||
prejoinDialogBackground: 'uiBackground', // Prejoin dialog background
|
||||
prejoinDialogDelimiter: 'ui03', // Prejoin dialog delimiter line
|
||||
prejoinDialogDelimiterText: 'text01', // Prejoin dialog delimiter text
|
||||
prejoinTitleText: 'text01', // Prejoin title text color
|
||||
prejoinRoomNameText: 'text01', // Prejoin room name text color
|
||||
prejoinWarningBackground: 'warning01', // Warning banner background
|
||||
prejoinWarningText: 'text04', // Warning banner text
|
||||
prejoinRecordingWarningText: 'text03', // Recording warning text
|
||||
prejoinActionButtonPrimary: 'action01', // Primary action button
|
||||
prejoinActionButtonPrimaryHover: 'action01Hover', // Primary button hover
|
||||
prejoinActionButtonPrimaryText: 'text01', // Primary button text
|
||||
prejoinActionButtonSecondary: 'action02', // Secondary action button
|
||||
prejoinActionButtonSecondaryHover: 'action02Hover', // Secondary button hover
|
||||
prejoinActionButtonSecondaryText: 'text04', // Secondary button text
|
||||
prejoinActionButtonDanger: 'actionDanger', // Danger button (leave)
|
||||
prejoinActionButtonDisabled: 'disabled01', // Disabled button
|
||||
prejoinCountryPickerBackground: 'ui01', // Country picker background
|
||||
prejoinCountryPickerBorder: 'ui03', // Country picker border
|
||||
prejoinCountryPickerText: 'text01', // Country picker text
|
||||
prejoinCountryRowBackground: 'action03', // Country row background
|
||||
prejoinCountryRowHover: 'action03Hover', // Country row hover
|
||||
prejoinDeviceStatusOk: 'success01', // Device status OK background
|
||||
prejoinDeviceStatusWarning: 'warning01', // Device status warning background
|
||||
prejoinDeviceStatusText: 'uiBackground', // Device status text
|
||||
|
||||
// Notifications
|
||||
notificationBackground: 'ui04', // Notification background
|
||||
notificationNormalIcon: 'action01', // Normal notification icon
|
||||
notificationError: 'iconError', // Error notification icon
|
||||
notificationSuccess: 'success01', // Success notification icon
|
||||
notificationWarning: 'warning01', // Warning notification icon
|
||||
notificationText: 'text04', // Notification text
|
||||
notificationActionText: 'action01', // Notification action text
|
||||
notificationErrorText: 'textError', // Error notification text
|
||||
notificationActionFocus: 'action01', // Notification action focus outline
|
||||
notificationCloseIcon: 'icon04', // Notification close icon
|
||||
|
||||
// Forms/Inputs
|
||||
inputBackground: 'field01', // Input field background
|
||||
inputBorder: 'surface03', // Input field border (same as ui02)
|
||||
inputText: 'textColor01', // Input field text (same as text01)
|
||||
inputPlaceholder: 'textColor02', // Input placeholder text (same as text02)
|
||||
|
||||
// Breakout Rooms
|
||||
breakoutRoomBackground: 'ui01', // Breakout rooms panel background
|
||||
breakoutRoomItemBackground: 'surface03', // Individual breakout room background
|
||||
breakoutRoomArrowBackground: 'ui02', // Breakout room arrow container background
|
||||
|
||||
// Settings
|
||||
settingsBackground: 'ui01', // Settings dialog background
|
||||
settingsSectionBackground: 'ui02', // Settings section background
|
||||
settingsTabText: 'text01', // Settings tab text
|
||||
settingsShortcutKey: 'surface05', // Keyboard shortcut key background
|
||||
settingsVideoPreviewBorder: 'action01Hover', // Video preview border (selected)
|
||||
settingsErrorIcon: 'iconError', // Error icon color
|
||||
|
||||
// Visitors
|
||||
visitorsCountBadge: 'warning02', // Visitors count badge background
|
||||
visitorsCountText: 'uiBackground', // Visitors count badge text
|
||||
visitorsCountIcon: 'icon04', // Visitors count icon
|
||||
visitorsQueueBackground: 'ui01', // Visitors queue panel background
|
||||
visitorsQueueText: 'text01', // Visitors queue text
|
||||
visitorsArrowBackground: 'ui02', // Visitors arrow container background
|
||||
|
||||
// Welcome Page
|
||||
welcomeBackground: 'surface01', // Welcome page background (same as uiBackground)
|
||||
welcomeCard: 'ui01', // Welcome page tab bar background
|
||||
welcomeTabActive: 'icon01', // Welcome page active tab icon
|
||||
welcomeTabInactive: 'icon03', // Welcome page inactive tab icon
|
||||
|
||||
// ----- Form Components -----
|
||||
|
||||
// Input
|
||||
inputLabel: 'text01', // Input field label text
|
||||
inputFieldBackground: 'ui02', // Input field background color
|
||||
inputFieldBorder: 'ui02', // Input field border color
|
||||
inputFieldText: 'text01', // Input field text color
|
||||
inputFieldPlaceholder: 'text02', // Input field placeholder text
|
||||
inputFieldDisabled: 'text03', // Input field disabled text
|
||||
inputFieldError: 'textError', // Input field error state
|
||||
inputFieldFocus: 'focus01', // Input field focus outline
|
||||
inputClearButton: 'transparent', // Input clear button background
|
||||
inputBottomLabel: 'text02', // Input bottom label text
|
||||
inputBottomLabelError: 'textError', // Input bottom label error text
|
||||
|
||||
// Select
|
||||
selectLabel: 'text01', // Select label text
|
||||
selectBackground: 'ui02', // Select background color
|
||||
selectText: 'text01', // Select text color
|
||||
selectDisabled: 'text03', // Select disabled text
|
||||
selectError: 'textError', // Select error state
|
||||
selectFocus: 'focus01', // Select focus outline
|
||||
selectIcon: 'icon01', // Select dropdown icon (enabled)
|
||||
selectIconDisabled: 'icon03', // Select dropdown icon (disabled)
|
||||
selectBottomLabel: 'text02', // Select bottom label text
|
||||
selectBottomLabelError: 'textError', // Select bottom label error text
|
||||
|
||||
// MultiSelect
|
||||
multiSelectBackground: 'ui01', // MultiSelect dropdown background
|
||||
multiSelectBorder: 'ui04', // MultiSelect dropdown border
|
||||
multiSelectItemText: 'text01', // MultiSelect item text
|
||||
multiSelectItemHover: 'ui02', // MultiSelect item hover background
|
||||
multiSelectItemDisabled: 'text03', // MultiSelect disabled item text
|
||||
|
||||
// Checkbox
|
||||
checkboxLabel: 'text01', // Checkbox label text
|
||||
checkboxBorder: 'icon03', // Checkbox border color
|
||||
checkboxChecked: 'action01', // Checkbox checked background
|
||||
checkboxDisabledBackground: 'ui02', // Checkbox disabled background
|
||||
checkboxDisabledBorder: 'surface05', // Checkbox disabled border
|
||||
checkboxDisabledChecked: 'ui02', // Checkbox disabled checked background
|
||||
checkboxIcon: 'icon01', // Checkbox check icon (enabled)
|
||||
checkboxIconDisabled: 'icon03', // Checkbox check icon (disabled)
|
||||
|
||||
// Switch
|
||||
switchBackground: 'ui01', // Switch background (unchecked)
|
||||
switchBackgroundOn: 'action01', // Switch background (checked)
|
||||
switchToggle: 'ui04', // Switch toggle circle
|
||||
switchToggleDisabled: 'ui03', // Switch toggle circle (disabled)
|
||||
switchFocus: 'focus01', // Switch focus outline
|
||||
|
||||
// Tabs
|
||||
tabText: 'text02', // Tab text (unselected)
|
||||
tabTextHover: 'text01', // Tab text (hover)
|
||||
tabTextSelected: 'text01', // Tab text (selected)
|
||||
tabTextDisabled: 'text03', // Tab text (disabled)
|
||||
tabBorder: 'ui05', // Tab bottom border (unselected)
|
||||
tabBorderHover: 'ui10', // Tab bottom border (hover)
|
||||
tabBorderSelected: 'action01', // Tab bottom border (selected)
|
||||
tabBorderDisabled: 'ui05', // Tab bottom border (disabled)
|
||||
tabFocus: 'focus01', // Tab focus outline
|
||||
tabBadgeBackground: 'warning01', // Tab count badge background
|
||||
tabBadgeText: 'text04', // Tab count badge text
|
||||
|
||||
// ListItem
|
||||
listItemText: 'text01', // List item text color
|
||||
listItemBackground: 'ui01', // List item default background
|
||||
listItemHover: 'surface03', // List item hover background
|
||||
listItemHighlighted: 'surface03', // List item highlighted/active background
|
||||
listItemBoxShadow: 'ui02', // List item actions box shadow color
|
||||
|
||||
// ClickableIcon
|
||||
clickableIconBackground: 'transparent', // Clickable icon background
|
||||
clickableIconHover: 'ui02', // Clickable icon hover background
|
||||
clickableIconActive: 'ui03', // Clickable icon active/pressed background
|
||||
clickableIconFocus: 'focus01', // Clickable icon focus outline
|
||||
|
||||
// Label
|
||||
labelBackground: 'ui04', // Label default background
|
||||
labelText: 'text01', // Label text color
|
||||
labelWhiteBackground: 'ui08', // Label white variant background
|
||||
labelWhiteText: 'text04', // Label white variant text
|
||||
labelWhiteIcon: 'surface01', // Label white variant icon
|
||||
|
||||
// Tooltip
|
||||
tooltipBackground: 'uiBackground', // Tooltip background color
|
||||
tooltipText: 'text01', // Tooltip text color
|
||||
|
||||
// Polls
|
||||
pollsBackground: 'surface03', // Poll container background
|
||||
pollsTitle: 'text01', // Poll title text
|
||||
pollsSubtitle: 'text02', // Poll subtitle/secondary text
|
||||
pollsQuestion: 'text01', // Poll question text
|
||||
pollsAnswer: 'text01', // Poll answer text
|
||||
pollsBarBackground: 'ui03', // Poll results bar background
|
||||
pollsBarPercentage: 'text01', // Poll results percentage text
|
||||
pollsVotersBackground: 'ui03', // Poll voters list background
|
||||
pollsVotersText: 'text01', // Poll voters list text
|
||||
pollsSeparator: 'ui03', // Poll section separator
|
||||
pollsSendLabel: 'text01', // Poll send button label
|
||||
pollsSendDisabled: 'text03', // Poll send button disabled label
|
||||
pollsPaneBackground: 'ui01', // Poll pane container background
|
||||
pollsPaneBorder: 'ui05', // Poll pane border
|
||||
pollsCreateBackground: 'uiBackground', // Poll create dialog background
|
||||
pollsCreateBorder: 'ui06', // Poll create dialog border
|
||||
|
||||
// Video Quality / Slider
|
||||
sliderKnob: 'text01', // Slider knob/thumb color
|
||||
sliderTrack: 'text03', // Slider track color
|
||||
sliderFocus: 'ui06', // Slider focus outline
|
||||
videoQualityText: 'text01', // Video quality dialog text
|
||||
videoQualityBackground: 'surface02', // Video quality dialog background
|
||||
|
||||
// Connection Indicator
|
||||
connectionIndicatorLost: 'ui05', // Connection indicator lost status
|
||||
connectionIndicatorOther: 'action01', // Connection indicator other status
|
||||
|
||||
// Device Selection
|
||||
deviceSelectorBackground: 'ui01', // Device selector background
|
||||
deviceSelectorText: 'text01', // Device selector text
|
||||
deviceSelectorBorder: 'ui03', // Device selector border
|
||||
deviceSelectorTextBackground: 'uiBackground', // Device selector text-only background
|
||||
deviceSelectorVideoPreview: 'uiBackground', // Device selector video preview background
|
||||
|
||||
// Invite / Dial-in
|
||||
dialInBackground: 'ui01', // Dial-in summary background
|
||||
dialInText: 'text01', // Dial-in summary text
|
||||
dialInSecondaryText: 'text02', // Dial-in summary secondary text
|
||||
|
||||
// Reactions
|
||||
reactionsMenuBackground: 'ui01', // Reactions menu background
|
||||
reactionsMenuBorder: 'ui02', // Reactions menu border
|
||||
|
||||
// Recording / Live Stream
|
||||
recordingBackground: 'ui01', // Recording panel background
|
||||
recordingText: 'text01', // Recording panel text
|
||||
recordingHighlightButton: 'ui04', // Recording highlight button background
|
||||
recordingHighlightButtonDisabled: 'text02', // Recording highlight button disabled background
|
||||
recordingHighlightButtonIcon: 'ui02', // Recording highlight button icon color
|
||||
recordingHighlightButtonIconDisabled: 'text03', // Recording highlight button disabled icon color
|
||||
recordingNotificationText: 'surface01', // Recording notification text color
|
||||
recordingNotificationAction: 'action01', // Recording notification action color
|
||||
|
||||
// Virtual Background
|
||||
virtualBackgroundBackground: 'ui01', // Virtual background picker background
|
||||
virtualBackgroundText: 'text01', // Virtual background picker text
|
||||
virtualBackgroundBorder: 'ui03', // Virtual background item border
|
||||
virtualBackgroundPreview: 'uiBackground', // Virtual background preview container
|
||||
|
||||
// Conference / Meeting
|
||||
conferenceTimerText: 'text01', // Conference timer text
|
||||
conferenceSubjectText: 'text01', // Conference subject text
|
||||
conferenceNoticeBackground: 'uiBackground', // Conference notice background
|
||||
conferenceNoticeText: 'text01', // Conference notice text
|
||||
conferenceRaisedHandLabelText: 'uiBackground', // Raised hands count label text
|
||||
conferenceRaisedHandLabelIcon: 'surface01', // Raised hands count label icon
|
||||
|
||||
// Subtitle Messages
|
||||
subtitleMessageBackground: 'ui02', // Subtitle message background
|
||||
subtitleMessageText: 'text01', // Subtitle message text
|
||||
subtitleMessageSender: 'text02', // Subtitle message sender name
|
||||
subtitleMessageTime: 'text03', // Subtitle message timestamp
|
||||
|
||||
// Language Selector
|
||||
languageSelectorBackground: 'ui01', // Language selector background
|
||||
languageSelectorText: 'text01', // Language selector text
|
||||
languageSelectorHover: 'ui02', // Language selector item hover
|
||||
|
||||
// Video Menu
|
||||
videoMenuBackground: 'ui01', // Video menu background
|
||||
videoMenuBorder: 'ui02', // Video menu border
|
||||
videoMenuText: 'text01', // Video menu text
|
||||
videoMenuSliderBackground: 'ui03', // Video menu slider background
|
||||
|
||||
// File Sharing
|
||||
fileSharingBackground: 'ui01', // File sharing panel background
|
||||
fileSharingText: 'text01', // File sharing text
|
||||
fileSharingEmptyText: 'text02', // File sharing empty state text
|
||||
fileSharingEmptyIcon: 'icon03', // File sharing empty state icon
|
||||
fileSharingItemBackground: 'surface03', // File sharing item background
|
||||
fileSharingItemBorder: 'ui02', // File sharing item hover/border
|
||||
|
||||
// Gifs
|
||||
gifsBackground: 'ui01', // GIFs panel background
|
||||
gifsText: 'text01', // GIFs panel text
|
||||
|
||||
// Whiteboard
|
||||
whiteboardBackground: 'ui03', // Whiteboard background
|
||||
whiteboardText: 'text01', // Whiteboard panel text
|
||||
|
||||
// Salesforce
|
||||
salesforceSearchBackground: 'field01', // Salesforce search input background
|
||||
salesforceSearchBorder: 'ui05', // Salesforce search input border
|
||||
salesforceSearchText: 'dialogText', // Salesforce search input text
|
||||
salesforceSearchPlaceholder: 'text03', // Salesforce search placeholder
|
||||
salesforceSearchIcon: 'text03', // Salesforce search icon
|
||||
|
||||
// Security Dialog
|
||||
securityDialogBackground: 'ui01', // Security dialog background
|
||||
securityDialogText: 'text01', // Security dialog text
|
||||
securityDialogSecondaryText: 'text02', // Security dialog secondary text
|
||||
securityDialogBorder: 'ui07', // Security dialog border color
|
||||
|
||||
// Deep Linking
|
||||
deepLinkingBackground: 'ui01', // Deep linking page content pane background
|
||||
deepLinkingBorder: 'ui03', // Deep linking page content pane border
|
||||
deepLinkingText: 'text01', // Deep linking page text
|
||||
deepLinkingSeparator: 'ui03', // Deep linking separator line
|
||||
deepLinkingLabelText: 'text02', // Deep linking label text
|
||||
deepLinkingLink: 'link01', // Deep linking link color
|
||||
|
||||
// Base React Components
|
||||
baseReactBackground: 'ui01', // Base react component background
|
||||
baseReactText: 'text01', // Base react component text
|
||||
baseReactBorder: 'ui03', // Base react component border
|
||||
|
||||
// Inline Dialog
|
||||
inlineDialogBackground: 'ui01', // Inline dialog background
|
||||
inlineDialogText: 'text01', // Inline dialog text
|
||||
inlineDialogBorder: 'ui02', // Inline dialog border
|
||||
|
||||
// Pre-meeting / Action Button
|
||||
actionButtonBackground: 'ui01', // Action button background (different from main buttons)
|
||||
actionButtonText: 'text01', // Action button text
|
||||
actionButtonBorder: 'ui03', // Action button border
|
||||
|
||||
// Audio Route Picker
|
||||
audioRoutePickerBackground: 'ui01', // Audio route picker background
|
||||
audioRoutePickerText: 'text01', // Audio route picker text
|
||||
audioRoutePickerBorder: 'ui03', // Audio route picker border
|
||||
|
||||
// Etherpad
|
||||
etherpadBackground: 'ui01', // Etherpad panel background
|
||||
etherpadText: 'text01', // Etherpad panel text
|
||||
|
||||
// Display Name
|
||||
displayNameBackground: 'ui01', // Display name background
|
||||
displayNameText: 'text01', // Display name text
|
||||
|
||||
// Car Mode
|
||||
carModeBackground: 'ui01', // Car mode background
|
||||
carModeText: 'text01', // Car mode text
|
||||
carModeBorder: 'ui03', // Car mode border
|
||||
|
||||
// ----- Links -----
|
||||
|
||||
link01: 'action01',
|
||||
|
||||
@@ -14,7 +14,7 @@ const useStyles = makeStyles()(theme => {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'fixed',
|
||||
color: theme.palette.dialogText,
|
||||
color: theme.palette.text01,
|
||||
...theme.typography.bodyLongRegular,
|
||||
top: 0,
|
||||
left: 0,
|
||||
@@ -49,13 +49,13 @@ const useStyles = makeStyles()(theme => {
|
||||
height: '100%',
|
||||
top: 0,
|
||||
left: 0,
|
||||
backgroundColor: theme.palette.dialogOverlay,
|
||||
backgroundColor: theme.palette.ui02,
|
||||
opacity: 0.75
|
||||
},
|
||||
|
||||
modal: {
|
||||
backgroundColor: theme.palette.dialogBackground,
|
||||
border: `1px solid ${theme.palette.dialogBorder}`,
|
||||
backgroundColor: theme.palette.ui01,
|
||||
border: `1px solid ${theme.palette.ui03}`,
|
||||
boxShadow: '0px 4px 25px 4px rgba(20, 20, 20, 0.6)',
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
display: 'flex',
|
||||
|
||||
@@ -47,7 +47,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
formControl: {
|
||||
...theme.typography.bodyLongRegular,
|
||||
color: theme.palette.checkboxLabel,
|
||||
color: theme.palette.text01,
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
|
||||
@@ -76,10 +76,10 @@ const useStyles = makeStyles()(theme => {
|
||||
backgroundColor: 'transparent',
|
||||
margin: '3px',
|
||||
font: 'inherit',
|
||||
color: theme.palette.checkboxBorder,
|
||||
color: theme.palette.icon03,
|
||||
width: '18px',
|
||||
height: '18px',
|
||||
border: `2px solid ${theme.palette.checkboxBorder}`,
|
||||
border: `2px solid ${theme.palette.icon03}`,
|
||||
borderRadius: '3px',
|
||||
|
||||
display: 'grid',
|
||||
@@ -90,7 +90,7 @@ const useStyles = makeStyles()(theme => {
|
||||
width: '18px',
|
||||
height: '18px',
|
||||
opacity: 0,
|
||||
backgroundColor: theme.palette.checkboxChecked,
|
||||
backgroundColor: theme.palette.action01,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
@@ -104,11 +104,11 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
backgroundColor: theme.palette.checkboxDisabledBackground,
|
||||
borderColor: theme.palette.checkboxDisabledBorder,
|
||||
backgroundColor: theme.palette.ui03,
|
||||
borderColor: theme.palette.ui04,
|
||||
|
||||
'&::before': {
|
||||
backgroundColor: theme.palette.checkboxDisabledChecked
|
||||
backgroundColor: theme.palette.ui04
|
||||
}
|
||||
},
|
||||
|
||||
@@ -173,7 +173,7 @@ const Checkbox = ({
|
||||
<Icon
|
||||
aria-hidden = { true }
|
||||
className = 'checkmark'
|
||||
color = { disabled ? theme.palette.checkboxIconDisabled : theme.palette.checkboxIcon }
|
||||
color = { disabled ? theme.palette.icon03 : theme.palette.icon01 }
|
||||
size = { 18 }
|
||||
src = { IconCheck } />
|
||||
</div>
|
||||
|
||||
@@ -16,22 +16,22 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
button: {
|
||||
padding: '2px',
|
||||
backgroundColor: theme.palette.clickableIconBackground,
|
||||
backgroundColor: theme.palette.action03,
|
||||
border: 0,
|
||||
outline: 0,
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.clickableIconHover
|
||||
backgroundColor: theme.palette.ui02
|
||||
},
|
||||
|
||||
'&.focus-visible': {
|
||||
outline: 0,
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.clickableIconFocus}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.palette.clickableIconActive
|
||||
backgroundColor: theme.palette.ui03
|
||||
},
|
||||
|
||||
'&.is-mobile': {
|
||||
|
||||
@@ -133,11 +133,11 @@ const MAX_HEIGHT = 400;
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
contextMenu: {
|
||||
backgroundColor: theme.palette.overflowMenuBackground,
|
||||
border: `1px solid ${theme.palette.overflowMenuBorder}`,
|
||||
backgroundColor: theme.palette.ui01,
|
||||
border: `1px solid ${theme.palette.ui04}`,
|
||||
borderRadius: `${Number(theme.shape.borderRadius)}px`,
|
||||
boxShadow: '0px 1px 2px rgba(41, 41, 41, 0.25)',
|
||||
color: theme.palette.overflowMenuItemText,
|
||||
color: theme.palette.text01,
|
||||
...theme.typography.bodyShortRegular,
|
||||
marginTop: '48px',
|
||||
position: 'absolute',
|
||||
|
||||
@@ -122,11 +122,11 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.overflowMenuItemHover
|
||||
backgroundColor: theme.palette.ui02
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.palette.overflowMenuItemHover
|
||||
backgroundColor: theme.palette.ui03
|
||||
},
|
||||
|
||||
'&.focus-visible': {
|
||||
@@ -137,7 +137,7 @@ const useStyles = makeStyles()(theme => {
|
||||
selected: {
|
||||
borderLeft: `3px solid ${theme.palette.action01Hover}`,
|
||||
paddingLeft: '13px',
|
||||
backgroundColor: theme.palette.overflowMenuItemHover
|
||||
backgroundColor: theme.palette.ui02
|
||||
},
|
||||
|
||||
contextMenuItemDisabled: {
|
||||
@@ -146,19 +146,19 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
contextMenuItemIconDisabled: {
|
||||
'& svg': {
|
||||
fill: `${theme.palette.overflowMenuItemDisabled} !important`
|
||||
fill: `${theme.palette.text03} !important`
|
||||
}
|
||||
},
|
||||
|
||||
contextMenuItemLabelDisabled: {
|
||||
color: theme.palette.overflowMenuItemDisabled,
|
||||
color: theme.palette.text03,
|
||||
|
||||
'&:hover': {
|
||||
background: 'none'
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.overflowMenuItemDisabled
|
||||
fill: theme.palette.text03
|
||||
}
|
||||
},
|
||||
|
||||
@@ -168,13 +168,13 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
contextMenuItemIcon: {
|
||||
'& svg': {
|
||||
fill: theme.palette.overflowMenuItemIcon
|
||||
fill: theme.palette.icon01
|
||||
}
|
||||
},
|
||||
|
||||
text: {
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.overflowMenuItemText
|
||||
color: theme.palette.text01
|
||||
},
|
||||
|
||||
drawerText: {
|
||||
|
||||
@@ -30,7 +30,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'& + &:not(:empty)': {
|
||||
borderTop: `1px solid ${theme.palette.overflowMenuSeparator}`
|
||||
borderTop: `1px solid ${theme.palette.ui03}`
|
||||
},
|
||||
|
||||
'&:first-of-type': {
|
||||
|
||||
@@ -24,7 +24,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
title: {
|
||||
color: theme.palette.dialogText,
|
||||
color: theme.palette.text01,
|
||||
...theme.typography.heading5,
|
||||
margin: 0,
|
||||
padding: 0
|
||||
|
||||
@@ -42,7 +42,7 @@ const useStyles = makeStyles()(theme => {
|
||||
flexDirection: 'column',
|
||||
minWidth: '211px',
|
||||
maxWidth: '100%',
|
||||
borderRight: `1px solid ${theme.palette.dialogBorder}`,
|
||||
borderRight: `1px solid ${theme.palette.ui03}`,
|
||||
|
||||
[`@media (max-width: ${MOBILE_BREAKPOINT}px)`]: {
|
||||
width: '100%',
|
||||
@@ -70,7 +70,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
title: {
|
||||
...theme.typography.heading5,
|
||||
color: `${theme.palette.dialogText} !important`,
|
||||
color: `${theme.palette.text01} !important`,
|
||||
margin: 0,
|
||||
padding: 0
|
||||
},
|
||||
@@ -301,7 +301,7 @@ const DialogWithTabs = ({
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [ selectedTabIndex, tabStates, tabs ]);
|
||||
}, [ selectedTabIndex, tabStates ]);
|
||||
|
||||
const closeIcon = useMemo(() => (
|
||||
<ClickableIcon
|
||||
|
||||
@@ -49,7 +49,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
label: {
|
||||
color: theme.palette.inputLabel,
|
||||
color: theme.palette.text01,
|
||||
...theme.typography.bodyShortRegular,
|
||||
marginBottom: theme.spacing(2),
|
||||
|
||||
@@ -64,9 +64,9 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
input: {
|
||||
backgroundColor: theme.palette.inputFieldBackground,
|
||||
background: theme.palette.inputFieldBackground,
|
||||
color: theme.palette.inputFieldText,
|
||||
backgroundColor: theme.palette.ui03,
|
||||
background: theme.palette.ui03,
|
||||
color: theme.palette.text01,
|
||||
...theme.typography.bodyShortRegular,
|
||||
padding: '10px 16px',
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
@@ -76,16 +76,16 @@ const useStyles = makeStyles()(theme => {
|
||||
width: '100%',
|
||||
|
||||
'&::placeholder': {
|
||||
color: theme.palette.inputFieldPlaceholder
|
||||
color: theme.palette.text02
|
||||
},
|
||||
|
||||
'&:focus': {
|
||||
outline: 0,
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.inputFieldFocus}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
color: theme.palette.inputFieldDisabled
|
||||
color: theme.palette.text03
|
||||
},
|
||||
|
||||
'&.is-mobile': {
|
||||
@@ -99,7 +99,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&.error': {
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.inputFieldError}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.textError}`
|
||||
},
|
||||
'&.clearable-input': {
|
||||
paddingRight: '46px'
|
||||
@@ -131,7 +131,7 @@ const useStyles = makeStyles()(theme => {
|
||||
right: '16px',
|
||||
top: '10px',
|
||||
cursor: 'pointer',
|
||||
backgroundColor: theme.palette.inputClearButton,
|
||||
backgroundColor: theme.palette.action03,
|
||||
border: 0,
|
||||
padding: 0
|
||||
},
|
||||
@@ -139,14 +139,14 @@ const useStyles = makeStyles()(theme => {
|
||||
bottomLabel: {
|
||||
marginTop: theme.spacing(2),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.inputBottomLabel,
|
||||
color: theme.palette.text02,
|
||||
|
||||
'&.is-mobile': {
|
||||
...theme.typography.bodyShortRegular
|
||||
},
|
||||
|
||||
'&.error': {
|
||||
color: theme.palette.inputBottomLabelError
|
||||
color: theme.palette.textError
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -83,7 +83,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
color: theme.palette.listItemText,
|
||||
color: theme.palette.text01,
|
||||
display: 'flex',
|
||||
...theme.typography.bodyShortBold,
|
||||
margin: `0 -${participantsPaneTheme.panePadding}px`,
|
||||
@@ -93,7 +93,7 @@ const useStyles = makeStyles()(theme => {
|
||||
minHeight: '40px',
|
||||
|
||||
'&:hover, &:focus-within': {
|
||||
backgroundColor: theme.palette.listItemHover,
|
||||
backgroundColor: theme.palette.ui02,
|
||||
|
||||
'& .indicators': {
|
||||
display: 'none'
|
||||
@@ -103,8 +103,8 @@ const useStyles = makeStyles()(theme => {
|
||||
display: 'flex',
|
||||
position: 'relative',
|
||||
top: 'auto',
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.listItemBoxShadow}`,
|
||||
backgroundColor: theme.palette.listItemHover
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.ui02}`,
|
||||
backgroundColor: theme.palette.ui02
|
||||
}
|
||||
},
|
||||
|
||||
@@ -115,14 +115,14 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
highlighted: {
|
||||
backgroundColor: theme.palette.listItemHighlighted,
|
||||
backgroundColor: theme.palette.ui02,
|
||||
|
||||
'& .actions': {
|
||||
display: 'flex',
|
||||
position: 'relative',
|
||||
top: 'auto',
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.listItemBoxShadow}`,
|
||||
backgroundColor: theme.palette.listItemHighlighted
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.ui02}`,
|
||||
backgroundColor: theme.palette.ui02
|
||||
}
|
||||
},
|
||||
|
||||
@@ -170,20 +170,20 @@ const useStyles = makeStyles()(theme => {
|
||||
actionsContainer: {
|
||||
position: 'absolute',
|
||||
top: '-1000px',
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.listItemBoxShadow}`,
|
||||
backgroundColor: theme.palette.listItemHover
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.ui02}`,
|
||||
backgroundColor: theme.palette.ui02
|
||||
},
|
||||
|
||||
actionsPermanent: {
|
||||
display: 'flex',
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.listItemBackground}`,
|
||||
backgroundColor: theme.palette.listItemBackground
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.ui01}`,
|
||||
backgroundColor: theme.palette.ui01
|
||||
},
|
||||
|
||||
actionsVisible: {
|
||||
display: 'flex',
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.listItemBoxShadow}`,
|
||||
backgroundColor: theme.palette.listItemHighlighted
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.ui02}`,
|
||||
backgroundColor: theme.palette.ui02
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -38,8 +38,8 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
marginTop: theme.spacing(2),
|
||||
width: '100%',
|
||||
backgroundColor: theme.palette.multiSelectBackground,
|
||||
border: `1px solid ${theme.palette.multiSelectBorder}`,
|
||||
backgroundColor: theme.palette.ui01,
|
||||
border: `1px solid ${theme.palette.ui04}`,
|
||||
borderRadius: `${Number(theme.shape.borderRadius)}px`,
|
||||
...theme.typography.bodyShortRegular,
|
||||
zIndex: 2,
|
||||
@@ -57,7 +57,7 @@ const useStyles = makeStyles()(theme => {
|
||||
inlineSize: 'calc(100% - 38px)',
|
||||
overflowWrap: 'break-word',
|
||||
marginLeft: theme.spacing(2),
|
||||
color: theme.palette.multiSelectItemText,
|
||||
color: theme.palette.text01,
|
||||
'&.with-remove': {
|
||||
// 60px because of the icon before the content and the remove button
|
||||
inlineSize: 'calc(100% - 60px)',
|
||||
@@ -76,15 +76,15 @@ const useStyles = makeStyles()(theme => {
|
||||
cursor: 'pointer',
|
||||
padding: `10px ${theme.spacing(3)}`,
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.multiSelectItemHover
|
||||
backgroundColor: theme.palette.ui02
|
||||
}
|
||||
},
|
||||
'&.disabled': {
|
||||
cursor: 'not-allowed',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.multiSelectBackground
|
||||
backgroundColor: theme.palette.ui01
|
||||
},
|
||||
color: theme.palette.multiSelectItemDisabled
|
||||
color: theme.palette.text03
|
||||
}
|
||||
},
|
||||
errorMessage: {
|
||||
|
||||
@@ -70,7 +70,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
label: {
|
||||
color: theme.palette.selectLabel,
|
||||
color: theme.palette.text01,
|
||||
...theme.typography.bodyShortRegular,
|
||||
marginBottom: theme.spacing(2),
|
||||
|
||||
@@ -84,11 +84,11 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
select: {
|
||||
backgroundColor: theme.palette.selectBackground,
|
||||
backgroundColor: theme.palette.ui03,
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
width: '100%',
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.selectText,
|
||||
color: theme.palette.text01,
|
||||
padding: '10px 16px',
|
||||
paddingRight: '42px',
|
||||
border: 0,
|
||||
@@ -99,11 +99,11 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
'&:focus': {
|
||||
outline: 0,
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.selectFocus}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
color: theme.palette.selectDisabled
|
||||
color: theme.palette.text03
|
||||
},
|
||||
|
||||
'&.is-mobile': {
|
||||
@@ -113,7 +113,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&.error': {
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.selectError}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.textError}`
|
||||
}
|
||||
},
|
||||
|
||||
@@ -132,14 +132,14 @@ const useStyles = makeStyles()(theme => {
|
||||
bottomLabel: {
|
||||
marginTop: theme.spacing(2),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.selectBottomLabel,
|
||||
color: theme.palette.text02,
|
||||
|
||||
'&.is-mobile': {
|
||||
...theme.typography.bodyShortRegular
|
||||
},
|
||||
|
||||
'&.error': {
|
||||
color: theme.palette.selectBottomLabelError
|
||||
color: theme.palette.textError
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -180,7 +180,7 @@ const Select = ({
|
||||
</select>
|
||||
<Icon
|
||||
className = { cx(classes.icon, isMobile && 'is-mobile') }
|
||||
color = { disabled ? theme.palette.selectIconDisabled : theme.palette.selectIcon }
|
||||
color = { disabled ? theme.palette.icon03 : theme.palette.icon01 }
|
||||
size = { 22 }
|
||||
src = { IconArrowDown } />
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
container: {
|
||||
position: 'relative',
|
||||
backgroundColor: theme.palette.switchBackground,
|
||||
backgroundColor: theme.palette.ui05,
|
||||
borderRadius: '12px',
|
||||
width: '40px',
|
||||
height: '24px',
|
||||
@@ -29,11 +29,11 @@ const useStyles = makeStyles()(theme => {
|
||||
display: 'inline-block',
|
||||
|
||||
'&.disabled': {
|
||||
backgroundColor: theme.palette.switchBackground,
|
||||
backgroundColor: theme.palette.ui05,
|
||||
cursor: 'default',
|
||||
|
||||
'& .toggle': {
|
||||
backgroundColor: theme.palette.switchToggleDisabled
|
||||
backgroundColor: theme.palette.ui03
|
||||
}
|
||||
},
|
||||
|
||||
@@ -45,7 +45,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
containerOn: {
|
||||
backgroundColor: theme.palette.switchBackgroundOn
|
||||
backgroundColor: theme.palette.action01
|
||||
},
|
||||
|
||||
toggle: {
|
||||
@@ -55,7 +55,7 @@ const useStyles = makeStyles()(theme => {
|
||||
zIndex: 5,
|
||||
top: '4px',
|
||||
left: '4px',
|
||||
backgroundColor: theme.palette.switchToggle,
|
||||
backgroundColor: theme.palette.ui10,
|
||||
borderRadius: '100%',
|
||||
transition: '.3s',
|
||||
|
||||
@@ -87,7 +87,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
'&.focus-visible + .toggle-checkbox-ring': {
|
||||
outline: 0,
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.switchFocus}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -29,13 +29,13 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
tab: {
|
||||
...theme.typography.bodyShortBold,
|
||||
color: theme.palette.tabText,
|
||||
color: theme.palette.text02,
|
||||
flex: 1,
|
||||
padding: '14px',
|
||||
background: 'none',
|
||||
border: 0,
|
||||
appearance: 'none',
|
||||
borderBottom: `2px solid ${theme.palette.tabBorder}`,
|
||||
borderBottom: `2px solid ${theme.palette.ui05}`,
|
||||
transition: 'color, border-color 0.2s',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
@@ -43,25 +43,25 @@ const useStyles = makeStyles()(theme => {
|
||||
borderRadius: 0,
|
||||
|
||||
'&:hover': {
|
||||
color: theme.palette.tabTextHover,
|
||||
borderColor: theme.palette.tabBorderHover
|
||||
color: theme.palette.text01,
|
||||
borderColor: theme.palette.ui10
|
||||
},
|
||||
|
||||
'&.focus-visible': {
|
||||
outline: 0,
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.tabFocus}`,
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`,
|
||||
border: 0,
|
||||
color: theme.palette.tabTextSelected
|
||||
color: theme.palette.text01
|
||||
},
|
||||
|
||||
'&.selected': {
|
||||
color: theme.palette.tabTextSelected,
|
||||
borderColor: theme.palette.tabBorderSelected
|
||||
color: theme.palette.text01,
|
||||
borderColor: theme.palette.action01
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
color: theme.palette.tabTextDisabled,
|
||||
borderColor: theme.palette.tabBorderDisabled
|
||||
color: theme.palette.text03,
|
||||
borderColor: theme.palette.ui05
|
||||
},
|
||||
|
||||
'&.is-mobile': {
|
||||
@@ -72,9 +72,9 @@ const useStyles = makeStyles()(theme => {
|
||||
badge: {
|
||||
...theme.typography.labelBold,
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.tabBadgeBackground,
|
||||
backgroundColor: theme.palette.warning01,
|
||||
borderRadius: theme.spacing(2),
|
||||
color: theme.palette.tabBadgeText,
|
||||
color: theme.palette.text04,
|
||||
display: 'inline-flex',
|
||||
height: theme.spacing(3),
|
||||
justifyContent: 'center',
|
||||
|
||||
@@ -11,23 +11,6 @@ export * from './constants.any';
|
||||
*/
|
||||
export const commonStyles = (theme: Theme) => {
|
||||
return {
|
||||
':root': {
|
||||
// Inject semantic tokens as CSS custom properties for use in SCSS
|
||||
'--toolbox-background-color': theme.palette.toolboxBackground,
|
||||
'--drawer-background-color': theme.palette.drawerBackground,
|
||||
'--toolbar-button-color': theme.palette.toolbarButton,
|
||||
'--toolbar-button-hover-color': theme.palette.toolbarButtonHover,
|
||||
'--toolbar-button-active-color': theme.palette.toolbarButtonActive,
|
||||
'--toolbar-icon-color': theme.palette.toolbarIcon,
|
||||
'--toolbar-icon-hover-color': theme.palette.toolbarIconHover,
|
||||
'--toolbar-icon-active-color': theme.palette.toolbarIconActive,
|
||||
'--overflow-menu-background-color': theme.palette.overflowMenuBackground,
|
||||
'--overflow-menu-item-text-color': theme.palette.overflowMenuItemText,
|
||||
'--overflow-menu-item-icon-color': theme.palette.overflowMenuItemIcon,
|
||||
'--overflow-menu-item-hover-color': theme.palette.overflowMenuItemHover,
|
||||
'--overflow-menu-item-disabled-color': theme.palette.overflowMenuItemDisabled
|
||||
},
|
||||
|
||||
'.empty-list': {
|
||||
listStyleType: 'none',
|
||||
margin: 0,
|
||||
@@ -56,7 +39,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
|
||||
'.overflow-menu-item': {
|
||||
alignItems: 'center',
|
||||
color: theme.palette.overflowMenuItemText,
|
||||
color: theme.palette.text01,
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
fontSize: '0.875rem',
|
||||
@@ -76,20 +59,20 @@ export const commonStyles = (theme: Theme) => {
|
||||
|
||||
'&.disabled': {
|
||||
cursor: 'initial',
|
||||
color: theme.palette.overflowMenuItemDisabled,
|
||||
color: theme.palette.text03,
|
||||
|
||||
'&:hover': {
|
||||
background: 'none'
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.overflowMenuItemDisabled
|
||||
fill: theme.palette.text03
|
||||
}
|
||||
},
|
||||
|
||||
'@media (hover: hover) and (pointer: fine)': {
|
||||
'&:hover': {
|
||||
background: theme.palette.overflowMenuItemHover
|
||||
background: theme.palette.action02Hover
|
||||
},
|
||||
'&.unclickable:hover': {
|
||||
background: 'inherit'
|
||||
@@ -117,14 +100,14 @@ export const commonStyles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.overflowMenuItemIcon,
|
||||
fill: theme.palette.text01,
|
||||
height: 20,
|
||||
width: 20
|
||||
}
|
||||
},
|
||||
|
||||
'.prejoin-dialog': {
|
||||
backgroundColor: theme.palette.prejoinDialogBackground,
|
||||
backgroundColor: theme.palette.uiBackground,
|
||||
boxShadow: '0px 2px 20px rgba(0, 0, 0, 0.5)',
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
color: '#fff',
|
||||
@@ -190,7 +173,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'.prejoin-dialog-delimiter': {
|
||||
background: theme.palette.prejoinDialogDelimiter,
|
||||
background: theme.palette.ui03,
|
||||
border: '0',
|
||||
height: '1px',
|
||||
margin: '0',
|
||||
@@ -211,8 +194,8 @@ export const commonStyles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'.prejoin-dialog-delimiter-txt': {
|
||||
background: theme.palette.prejoinDialogBackground,
|
||||
color: theme.palette.prejoinDialogDelimiterText,
|
||||
background: theme.palette.uiBackground,
|
||||
color: theme.palette.text01,
|
||||
fontSize: '0.75rem',
|
||||
textTransform: 'uppercase' as const,
|
||||
padding: `0 ${theme.spacing(2)}`
|
||||
@@ -236,11 +219,11 @@ export const commonStyles = (theme: Theme) => {
|
||||
|
||||
'@media (hover: hover) and (pointer: fine)': {
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.toolboxIconHover
|
||||
backgroundColor: theme.palette.ui04
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.palette.toolboxIconActive
|
||||
backgroundColor: theme.palette.ui03
|
||||
}
|
||||
},
|
||||
[theme.breakpoints.down(320)]: {
|
||||
@@ -249,7 +232,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'&.toggled': {
|
||||
backgroundColor: theme.palette.toolboxIconToggled
|
||||
backgroundColor: theme.palette.ui03
|
||||
},
|
||||
|
||||
'&.disabled': {
|
||||
@@ -257,13 +240,13 @@ export const commonStyles = (theme: Theme) => {
|
||||
backgroundColor: `${theme.palette.disabled01} !important`,
|
||||
|
||||
'& svg': {
|
||||
fill: `${theme.palette.icon03} !important`
|
||||
fill: `${theme.palette.text03} !important`
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'.toolbox-button': {
|
||||
color: theme.palette.toolbarIcon,
|
||||
color: theme.palette.text01,
|
||||
cursor: 'pointer',
|
||||
display: 'inline-block',
|
||||
lineHeight: '3rem',
|
||||
@@ -271,7 +254,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'.toolbox-content-items': {
|
||||
background: theme.palette.toolboxBackground,
|
||||
background: theme.palette.ui01,
|
||||
borderRadius: 6,
|
||||
margin: '0 auto',
|
||||
padding: 6,
|
||||
|
||||
11
react/features/base/ui/types.d.ts
vendored
11
react/features/base/ui/types.d.ts
vendored
@@ -1,11 +0,0 @@
|
||||
import '@mui/material/styles';
|
||||
|
||||
import { IPalette, ITypography } from './types';
|
||||
|
||||
declare module '@mui/material/styles' {
|
||||
interface Palette extends IPalette {}
|
||||
interface PaletteOptions extends Partial<IPalette> {}
|
||||
|
||||
interface Typography extends ITypography {}
|
||||
interface TypographyOptions extends Partial<ITypography> {}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ interface ITypographyType {
|
||||
lineHeight: string;
|
||||
}
|
||||
|
||||
/* eslint-disable typescript-sort-keys/interface */
|
||||
export interface IPalette {
|
||||
action01: string;
|
||||
action01Active: string;
|
||||
@@ -59,324 +58,6 @@ export interface IPalette {
|
||||
uiBackground: string;
|
||||
warning01: string;
|
||||
warning02: string;
|
||||
|
||||
// Semantic tokens (component-based, more descriptive names)
|
||||
breakoutRoomArrowBackground: string;
|
||||
breakoutRoomBackground: string;
|
||||
breakoutRoomItemBackground: string;
|
||||
chatBackground: string;
|
||||
chatBackdrop: string;
|
||||
chatEmptyText: string;
|
||||
chatInputBackground: string;
|
||||
chatInputBorder: string;
|
||||
chatLink: string;
|
||||
chatLobbyMessageBubble: string;
|
||||
chatLobbyMessageNotice: string;
|
||||
chatLobbyRecipientContainer: string;
|
||||
chatMessageLocal: string;
|
||||
chatMessagePrivate: string;
|
||||
chatMessageRemote: string;
|
||||
chatMessageText: string;
|
||||
chatPrivateNotice: string;
|
||||
chatRecipientCancelIcon: string;
|
||||
chatRecipientContainer: string;
|
||||
chatRecipientText: string;
|
||||
chatReplyIcon: string;
|
||||
chatSenderName: string;
|
||||
chatTimestamp: string;
|
||||
dialogBackground: string;
|
||||
dialogBorder: string;
|
||||
dialogOverlay: string;
|
||||
dialogSecondaryText: string;
|
||||
dialogText: string;
|
||||
drawerBackground: string;
|
||||
filmstripBackground: string;
|
||||
filmstripBackgroundHover: string;
|
||||
filmstripDragHandle: string;
|
||||
filmstripDragHandleHover: string;
|
||||
inputBackground: string;
|
||||
inputBorder: string;
|
||||
inputPlaceholder: string;
|
||||
inputText: string;
|
||||
largeVideoBackground: string;
|
||||
largeVideoPlaceholder: string;
|
||||
lobbyBackground: string;
|
||||
lobbyPreviewBackground: string;
|
||||
notificationActionFocus: string;
|
||||
notificationActionText: string;
|
||||
notificationBackground: string;
|
||||
notificationCloseIcon: string;
|
||||
notificationError: string;
|
||||
notificationErrorText: string;
|
||||
notificationNormalIcon: string;
|
||||
notificationSuccess: string;
|
||||
notificationText: string;
|
||||
notificationWarning: string;
|
||||
overflowMenuBackground: string;
|
||||
overflowMenuBorder: string;
|
||||
overflowMenuItemDisabled: string;
|
||||
overflowMenuItemHover: string;
|
||||
overflowMenuItemIcon: string;
|
||||
overflowMenuItemText: string;
|
||||
overflowMenuSeparator: string;
|
||||
participantActionButton: string;
|
||||
participantCounterBadge: string;
|
||||
participantCounterText: string;
|
||||
participantItemBackground: string;
|
||||
participantItemBorder: string;
|
||||
participantItemHover: string;
|
||||
participantLinkText: string;
|
||||
participantModeratorLabel: string;
|
||||
participantRaisedHandBadge: string;
|
||||
participantRaisedHandIcon: string;
|
||||
participantSectionText: string;
|
||||
participantsPaneBackground: string;
|
||||
participantWarningText: string;
|
||||
preMeetingBackground: string;
|
||||
preMeetingPreview: string;
|
||||
prejoinActionButtonDanger: string;
|
||||
prejoinActionButtonDisabled: string;
|
||||
prejoinActionButtonPrimary: string;
|
||||
prejoinActionButtonPrimaryHover: string;
|
||||
prejoinActionButtonPrimaryText: string;
|
||||
prejoinActionButtonSecondary: string;
|
||||
prejoinActionButtonSecondaryHover: string;
|
||||
prejoinActionButtonSecondaryText: string;
|
||||
prejoinCountryPickerBackground: string;
|
||||
prejoinCountryPickerBorder: string;
|
||||
prejoinCountryPickerText: string;
|
||||
prejoinCountryRowBackground: string;
|
||||
prejoinCountryRowHover: string;
|
||||
prejoinDeviceStatusOk: string;
|
||||
prejoinDeviceStatusText: string;
|
||||
prejoinDeviceStatusWarning: string;
|
||||
prejoinDialogBackground: string;
|
||||
prejoinDialogDelimiter: string;
|
||||
prejoinDialogDelimiterText: string;
|
||||
prejoinRecordingWarningText: string;
|
||||
prejoinRoomNameText: string;
|
||||
prejoinTitleText: string;
|
||||
prejoinWarningBackground: string;
|
||||
prejoinWarningText: string;
|
||||
settingsBackground: string;
|
||||
settingsErrorIcon: string;
|
||||
settingsSectionBackground: string;
|
||||
settingsShortcutKey: string;
|
||||
settingsTabText: string;
|
||||
settingsVideoPreviewBorder: string;
|
||||
speakerStatsAvatarLeft: string;
|
||||
speakerStatsBackground: string;
|
||||
speakerStatsBorder: string;
|
||||
speakerStatsHeaderBackground: string;
|
||||
speakerStatsLabelText: string;
|
||||
speakerStatsRowAlternate: string;
|
||||
speakerStatsRowBackground: string;
|
||||
speakerStatsSearchBackground: string;
|
||||
speakerStatsSearchBorder: string;
|
||||
speakerStatsSearchIcon: string;
|
||||
speakerStatsSearchPlaceholder: string;
|
||||
speakerStatsSearchText: string;
|
||||
speakerStatsSuccessBar: string;
|
||||
thumbnailBackground: string;
|
||||
thumbnailBorder: string;
|
||||
thumbnailHover: string;
|
||||
thumbnailRaisedHandIcon: string;
|
||||
thumbnailTintBackground: string;
|
||||
thumbnailVideoBackground: string;
|
||||
toolbarButton: string;
|
||||
toolbarButtonActive: string;
|
||||
toolbarButtonHover: string;
|
||||
toolbarIcon: string;
|
||||
toolbarIconActive: string;
|
||||
toolbarIconHover: string;
|
||||
toolboxBackground: string;
|
||||
toolboxIconActive: string;
|
||||
toolboxIconHover: string;
|
||||
toolboxIconToggled: string;
|
||||
visitorsArrowBackground: string;
|
||||
visitorsCountBadge: string;
|
||||
visitorsCountIcon: string;
|
||||
visitorsCountText: string;
|
||||
visitorsQueueBackground: string;
|
||||
visitorsQueueText: string;
|
||||
welcomeBackground: string;
|
||||
welcomeCard: string;
|
||||
welcomeTabActive: string;
|
||||
welcomeTabInactive: string;
|
||||
|
||||
// Form components
|
||||
actionButtonBackground: string;
|
||||
actionButtonBorder: string;
|
||||
actionButtonText: string;
|
||||
audioRoutePickerBackground: string;
|
||||
audioRoutePickerBorder: string;
|
||||
audioRoutePickerText: string;
|
||||
baseReactBackground: string;
|
||||
baseReactBorder: string;
|
||||
baseReactText: string;
|
||||
carModeBackground: string;
|
||||
carModeBorder: string;
|
||||
carModeText: string;
|
||||
checkboxBorder: string;
|
||||
checkboxChecked: string;
|
||||
checkboxDisabledBackground: string;
|
||||
checkboxDisabledBorder: string;
|
||||
checkboxDisabledChecked: string;
|
||||
checkboxIcon: string;
|
||||
checkboxIconDisabled: string;
|
||||
checkboxLabel: string;
|
||||
clickableIconActive: string;
|
||||
clickableIconBackground: string;
|
||||
clickableIconFocus: string;
|
||||
clickableIconHover: string;
|
||||
conferenceNoticeBackground: string;
|
||||
conferenceNoticeText: string;
|
||||
conferenceRaisedHandLabelIcon: string;
|
||||
conferenceRaisedHandLabelText: string;
|
||||
conferenceSubjectText: string;
|
||||
conferenceTimerText: string;
|
||||
connectionIndicatorLost: string;
|
||||
connectionIndicatorOther: string;
|
||||
deepLinkingBackground: string;
|
||||
deepLinkingBorder: string;
|
||||
deepLinkingLabelText: string;
|
||||
deepLinkingLink: string;
|
||||
deepLinkingSeparator: string;
|
||||
deepLinkingText: string;
|
||||
deviceSelectorBackground: string;
|
||||
deviceSelectorBorder: string;
|
||||
deviceSelectorText: string;
|
||||
deviceSelectorTextBackground: string;
|
||||
deviceSelectorVideoPreview: string;
|
||||
dialInBackground: string;
|
||||
dialInSecondaryText: string;
|
||||
dialInText: string;
|
||||
displayNameBackground: string;
|
||||
displayNameText: string;
|
||||
etherpadBackground: string;
|
||||
etherpadText: string;
|
||||
fileSharingBackground: string;
|
||||
fileSharingEmptyIcon: string;
|
||||
fileSharingEmptyText: string;
|
||||
fileSharingItemBackground: string;
|
||||
fileSharingItemBorder: string;
|
||||
fileSharingText: string;
|
||||
gifsBackground: string;
|
||||
gifsText: string;
|
||||
inlineDialogBackground: string;
|
||||
inlineDialogBorder: string;
|
||||
inlineDialogText: string;
|
||||
inputBottomLabel: string;
|
||||
inputBottomLabelError: string;
|
||||
inputClearButton: string;
|
||||
inputFieldBackground: string;
|
||||
inputFieldBorder: string;
|
||||
inputFieldDisabled: string;
|
||||
inputFieldError: string;
|
||||
inputFieldFocus: string;
|
||||
inputFieldPlaceholder: string;
|
||||
inputFieldText: string;
|
||||
inputLabel: string;
|
||||
labelBackground: string;
|
||||
labelText: string;
|
||||
labelWhiteBackground: string;
|
||||
labelWhiteIcon: string;
|
||||
labelWhiteText: string;
|
||||
languageSelectorBackground: string;
|
||||
languageSelectorHover: string;
|
||||
languageSelectorText: string;
|
||||
listItemBackground: string;
|
||||
listItemBoxShadow: string;
|
||||
listItemHighlighted: string;
|
||||
listItemHover: string;
|
||||
listItemText: string;
|
||||
multiSelectBackground: string;
|
||||
multiSelectBorder: string;
|
||||
multiSelectItemDisabled: string;
|
||||
multiSelectItemHover: string;
|
||||
multiSelectItemText: string;
|
||||
pollsAnswer: string;
|
||||
pollsBackground: string;
|
||||
pollsBarBackground: string;
|
||||
pollsBarPercentage: string;
|
||||
pollsCreateBackground: string;
|
||||
pollsCreateBorder: string;
|
||||
pollsPaneBackground: string;
|
||||
pollsPaneBorder: string;
|
||||
pollsQuestion: string;
|
||||
pollsSendDisabled: string;
|
||||
pollsSendLabel: string;
|
||||
pollsSeparator: string;
|
||||
pollsSubtitle: string;
|
||||
pollsTitle: string;
|
||||
pollsVotersBackground: string;
|
||||
pollsVotersText: string;
|
||||
reactionsMenuBackground: string;
|
||||
reactionsMenuBorder: string;
|
||||
recordingBackground: string;
|
||||
recordingHighlightButton: string;
|
||||
recordingHighlightButtonDisabled: string;
|
||||
recordingHighlightButtonIcon: string;
|
||||
recordingHighlightButtonIconDisabled: string;
|
||||
recordingNotificationAction: string;
|
||||
recordingNotificationText: string;
|
||||
recordingText: string;
|
||||
securityDialogBackground: string;
|
||||
securityDialogBorder: string;
|
||||
securityDialogSecondaryText: string;
|
||||
securityDialogText: string;
|
||||
selectBackground: string;
|
||||
selectBottomLabel: string;
|
||||
selectBottomLabelError: string;
|
||||
selectDisabled: string;
|
||||
selectError: string;
|
||||
selectFocus: string;
|
||||
selectIcon: string;
|
||||
selectIconDisabled: string;
|
||||
selectLabel: string;
|
||||
selectText: string;
|
||||
sliderFocus: string;
|
||||
sliderKnob: string;
|
||||
sliderTrack: string;
|
||||
subtitleMessageBackground: string;
|
||||
subtitleMessageSender: string;
|
||||
subtitleMessageText: string;
|
||||
subtitleMessageTime: string;
|
||||
switchBackground: string;
|
||||
switchBackgroundOn: string;
|
||||
switchFocus: string;
|
||||
switchToggle: string;
|
||||
switchToggleDisabled: string;
|
||||
tabBadgeBackground: string;
|
||||
tabBadgeText: string;
|
||||
tabBorder: string;
|
||||
tabBorderDisabled: string;
|
||||
tabBorderHover: string;
|
||||
tabBorderSelected: string;
|
||||
tabFocus: string;
|
||||
tabText: string;
|
||||
tabTextDisabled: string;
|
||||
tabTextHover: string;
|
||||
tabTextSelected: string;
|
||||
tooltipBackground: string;
|
||||
tooltipText: string;
|
||||
videoMenuBackground: string;
|
||||
videoMenuBorder: string;
|
||||
videoMenuSliderBackground: string;
|
||||
videoMenuText: string;
|
||||
videoQualityBackground: string;
|
||||
videoQualityText: string;
|
||||
virtualBackgroundBackground: string;
|
||||
virtualBackgroundBorder: string;
|
||||
virtualBackgroundPreview: string;
|
||||
virtualBackgroundText: string;
|
||||
whiteboardBackground: string;
|
||||
whiteboardText: string;
|
||||
salesforceSearchBackground: string;
|
||||
salesforceSearchBorder: string;
|
||||
salesforceSearchIcon: string;
|
||||
salesforceSearchPlaceholder: string;
|
||||
salesforceSearchText: string;
|
||||
}
|
||||
|
||||
export interface ITypography {
|
||||
|
||||
@@ -11,49 +11,13 @@ import * as tokens from './tokens.json';
|
||||
*/
|
||||
export function createColorTokens(colorMap: Object): any {
|
||||
const allTokens = merge({}, tokens, jitsiTokens);
|
||||
const result: any = {};
|
||||
|
||||
// First pass: resolve tokens that reference allTokens directly
|
||||
Object.entries(colorMap).forEach(([ token, value ]: [any, string]) => {
|
||||
const color = allTokens[value as keyof typeof allTokens] || value;
|
||||
return Object.entries(colorMap)
|
||||
.reduce((result, [ token, value ]: [any, string]) => {
|
||||
const color = allTokens[value as keyof typeof allTokens] || value;
|
||||
|
||||
result[token] = color;
|
||||
});
|
||||
|
||||
// Second pass: resolve semantic tokens that reference other colorMap entries
|
||||
// Recursively resolve until we get actual color values
|
||||
const resolveToken = (value: string, depth = 0): string => {
|
||||
// Prevent infinite loops
|
||||
if (depth > 10) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// If it's already a color (starts with # or rgb/rgba), return it
|
||||
if (value.startsWith('#') || value.startsWith('rgb')) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// Look up in the result map first (for colorMap token references)
|
||||
if (result[value]) {
|
||||
return resolveToken(result[value], depth + 1);
|
||||
}
|
||||
|
||||
// Then look up in allTokens
|
||||
const resolved = allTokens[value as keyof typeof allTokens];
|
||||
|
||||
if (resolved && resolved !== value && typeof resolved === 'string') {
|
||||
return resolveToken(resolved, depth + 1);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
// Third pass: recursively resolve all values
|
||||
Object.entries(result).forEach(([ token, value ]) => {
|
||||
result[token] = resolveToken(String(value));
|
||||
});
|
||||
|
||||
return result;
|
||||
return Object.assign(result, { [token]: color });
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@ export default {
|
||||
|
||||
button: {
|
||||
marginBottom: BaseTheme.spacing[4],
|
||||
marginHorizontal: BaseTheme.spacing[3]
|
||||
marginHorizontal: BaseTheme.spacing[2]
|
||||
},
|
||||
|
||||
collapsibleList: {
|
||||
|
||||
@@ -44,16 +44,6 @@ export const getMainRoom = (stateful: IStateful) => {
|
||||
* @returns {IRoomsInfo} The rooms info.
|
||||
*/
|
||||
export const getRoomsInfo = (stateful: IStateful) => {
|
||||
const state = toState(stateful);
|
||||
const localParticipant = getLocalParticipant(stateful);
|
||||
const jwtUser = state['features/base/jwt']?.user;
|
||||
const localUserContext = jwtUser ? {
|
||||
id: jwtUser.id,
|
||||
name: jwtUser.name
|
||||
} : {
|
||||
id: localParticipant?.jwtId,
|
||||
name: localParticipant?.name
|
||||
};
|
||||
const breakoutRooms = getBreakoutRooms(stateful);
|
||||
const conference = getCurrentConference(stateful);
|
||||
|
||||
@@ -67,6 +57,7 @@ export const getRoomsInfo = (stateful: IStateful) => {
|
||||
const conferenceParticipants = conference?.getParticipants()
|
||||
.filter((participant: IJitsiParticipant) => !participant.isHidden());
|
||||
|
||||
const localParticipant = getLocalParticipant(stateful);
|
||||
let localParticipantInfo;
|
||||
|
||||
if (localParticipant) {
|
||||
@@ -74,8 +65,7 @@ export const getRoomsInfo = (stateful: IStateful) => {
|
||||
role: localParticipant.role,
|
||||
displayName: localParticipant.name,
|
||||
avatarUrl: localParticipant.loadableAvatarUrl,
|
||||
id: localParticipant.id,
|
||||
userContext: localUserContext
|
||||
id: localParticipant.id
|
||||
};
|
||||
}
|
||||
|
||||
@@ -96,8 +86,7 @@ export const getRoomsInfo = (stateful: IStateful) => {
|
||||
role: participantItem.getRole(),
|
||||
displayName: participantItem.getDisplayName(),
|
||||
avatarUrl: storeParticipant?.loadableAvatarUrl,
|
||||
id: participantItem.getId(),
|
||||
userContext: storeParticipant?.userContext
|
||||
id: participantItem.getId()
|
||||
} as IRoomInfoParticipant;
|
||||
}) ]
|
||||
: [ localParticipantInfo ]
|
||||
@@ -121,18 +110,13 @@ export const getRoomsInfo = (stateful: IStateful) => {
|
||||
const storeParticipant = getParticipantById(stateful,
|
||||
ids.length > 1 ? ids[1] : participantItem.jid);
|
||||
|
||||
// Check if this is the local participant
|
||||
const isLocal = storeParticipant?.id === localParticipant?.id;
|
||||
const userContext = isLocal ? localUserContext : (storeParticipant?.userContext || participantItem.userContext);
|
||||
|
||||
return {
|
||||
jid: participantItem?.jid,
|
||||
role: participantItem?.role,
|
||||
displayName: participantItem?.displayName,
|
||||
avatarUrl: storeParticipant?.loadableAvatarUrl,
|
||||
id: storeParticipant ? storeParticipant.id
|
||||
: participantLongId,
|
||||
userContext
|
||||
: participantLongId
|
||||
} as IRoomInfoParticipant;
|
||||
}) : []
|
||||
} as IRoomInfo;
|
||||
|
||||
@@ -44,59 +44,19 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
|
||||
|
||||
switch (type) {
|
||||
case UPDATE_BREAKOUT_ROOMS: {
|
||||
// Enrich participants with userContext from Redux store
|
||||
// edit name if it was overwritten
|
||||
if (!action.updatedNames) {
|
||||
const state = getState();
|
||||
const { overwrittenNameList, local: localParticipant } = state['features/base/participants'];
|
||||
const jwtUser = state['features/base/jwt']?.user;
|
||||
const localUserContext = jwtUser ? {
|
||||
id: jwtUser.id,
|
||||
name: jwtUser.name
|
||||
} : {
|
||||
id: localParticipant?.jwtId,
|
||||
name: localParticipant?.name
|
||||
};
|
||||
const { overwrittenNameList } = getState()['features/base/participants'];
|
||||
|
||||
// Get existing userContext cache
|
||||
const existingCache = state['features/breakout-rooms'].userContextCache || {};
|
||||
const newCache = { ...existingCache };
|
||||
if (Object.keys(overwrittenNameList).length > 0) {
|
||||
const newRooms: IRooms = {};
|
||||
|
||||
const newRooms: IRooms = {};
|
||||
Object.entries(action.rooms as IRooms).forEach(([ key, r ]) => {
|
||||
let participants = r?.participants || {};
|
||||
let jid;
|
||||
|
||||
Object.entries(action.rooms as IRooms).forEach(([ key, r ]) => {
|
||||
let participants = r?.participants || {};
|
||||
|
||||
// Add userContext to each participant
|
||||
const enhancedParticipants: typeof participants = {};
|
||||
|
||||
for (const [ participantJid, participantData ] of Object.entries(participants)) {
|
||||
const ids = participantJid.split('/');
|
||||
const participantId = ids.length > 1 ? ids[1] : participantData.jid;
|
||||
const storeParticipant = getParticipantById(state, participantId);
|
||||
const isLocal = storeParticipant?.id === localParticipant?.id;
|
||||
|
||||
// Try to get userContext from: local, store, cache, or incoming data
|
||||
const userContext = isLocal
|
||||
? localUserContext
|
||||
: (storeParticipant?.userContext || newCache[participantId] || participantData.userContext);
|
||||
|
||||
// Update cache if we have userContext
|
||||
if (userContext && participantId) {
|
||||
newCache[participantId] = userContext;
|
||||
}
|
||||
|
||||
enhancedParticipants[participantJid] = {
|
||||
...participantData,
|
||||
userContext
|
||||
};
|
||||
}
|
||||
|
||||
participants = enhancedParticipants;
|
||||
|
||||
// Apply overwritten display names
|
||||
if (Object.keys(overwrittenNameList).length > 0) {
|
||||
for (const id of Object.keys(overwrittenNameList)) {
|
||||
const jid = Object.keys(participants).find(p => p.slice(p.indexOf('/') + 1) === id);
|
||||
jid = Object.keys(participants).find(p => p.slice(p.indexOf('/') + 1) === id);
|
||||
|
||||
if (jid) {
|
||||
participants = {
|
||||
@@ -108,16 +68,15 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newRooms[key] = {
|
||||
...r,
|
||||
participants
|
||||
};
|
||||
});
|
||||
newRooms[key] = {
|
||||
...r,
|
||||
participants
|
||||
};
|
||||
});
|
||||
|
||||
action.rooms = newRooms;
|
||||
action.userContextCache = newCache;
|
||||
action.rooms = newRooms;
|
||||
}
|
||||
}
|
||||
|
||||
// edit the chat history to match names for participants in breakout rooms
|
||||
|
||||
@@ -10,19 +10,12 @@ import { IRooms } from './types';
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
rooms: {},
|
||||
roomCounter: 0,
|
||||
userContextCache: {}
|
||||
roomCounter: 0
|
||||
};
|
||||
|
||||
export interface IBreakoutRoomsState {
|
||||
roomCounter: number;
|
||||
rooms: IRooms;
|
||||
userContextCache: {
|
||||
[participantId: string]: {
|
||||
id?: string;
|
||||
name?: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,13 +29,12 @@ ReducerRegistry.register<IBreakoutRoomsState>(FEATURE_KEY, (state = DEFAULT_STAT
|
||||
roomCounter: action.roomCounter
|
||||
};
|
||||
case UPDATE_BREAKOUT_ROOMS: {
|
||||
const { roomCounter, rooms, userContextCache } = action;
|
||||
const { roomCounter, rooms } = action;
|
||||
|
||||
return {
|
||||
...state,
|
||||
roomCounter,
|
||||
rooms,
|
||||
userContextCache: userContextCache || state.userContextCache
|
||||
rooms
|
||||
};
|
||||
}
|
||||
case _RESET_BREAKOUT_ROOMS: {
|
||||
|
||||
@@ -8,10 +8,6 @@ export interface IRoom {
|
||||
displayName: string;
|
||||
jid: string;
|
||||
role: string;
|
||||
userContext?: {
|
||||
id?: string;
|
||||
name?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -37,8 +33,4 @@ export interface IRoomInfoParticipant {
|
||||
id: string;
|
||||
jid: string;
|
||||
role: string;
|
||||
userContext?: {
|
||||
id?: string;
|
||||
name?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ export function openChat(participant?: IParticipant | undefined | Object, disabl
|
||||
if (disablePolls) {
|
||||
navigate(screen.conference.chat);
|
||||
} else {
|
||||
navigate(screen.conference.chatTabs.main);
|
||||
navigate(screen.conference.chatandpolls.main);
|
||||
}
|
||||
|
||||
dispatch(setFocusedTab(ChatTabs.CHAT));
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
import React, { ComponentType, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../app/types';
|
||||
import { openDialog } from '../../base/dialog/actions';
|
||||
import { IMessageGroup, groupMessagesBySender } from '../../base/util/messageGrouping';
|
||||
// @ts-ignore
|
||||
import { StartRecordingDialog } from '../../recording/components/Recording';
|
||||
import { setRequestingSubtitles } from '../../subtitles/actions.any';
|
||||
import { canStartSubtitles } from '../../subtitles/functions.any';
|
||||
import { ISubtitle } from '../../subtitles/types';
|
||||
import { isTranscribing } from '../../transcribing/functions';
|
||||
|
||||
export type AbstractProps = {
|
||||
canStartSubtitles: boolean;
|
||||
filteredSubtitles: ISubtitle[];
|
||||
groupedSubtitles: IMessageGroup<ISubtitle>[];
|
||||
isButtonPressed: boolean;
|
||||
isTranscribing: boolean;
|
||||
startClosedCaptions: () => void;
|
||||
};
|
||||
|
||||
const AbstractClosedCaptions = (Component: ComponentType<AbstractProps>) => () => {
|
||||
const dispatch = useDispatch();
|
||||
const subtitles = useSelector((state: IReduxState) => state['features/subtitles'].subtitlesHistory);
|
||||
const language = useSelector((state: IReduxState) => state['features/subtitles']._language);
|
||||
const selectedLanguage = language?.replace('translation-languages:', '');
|
||||
const _isTranscribing = useSelector(isTranscribing);
|
||||
const _canStartSubtitles = useSelector(canStartSubtitles);
|
||||
const [ isButtonPressed, setButtonPressed ] = useState(false);
|
||||
const subtitlesError = useSelector((state: IReduxState) => state['features/subtitles']._hasError);
|
||||
const isAsyncTranscriptionEnabled = useSelector((state: IReduxState) =>
|
||||
state['features/base/conference'].conference?.getMetadataHandler()?.getMetadata()?.asyncTranscription);
|
||||
|
||||
const filteredSubtitles = useMemo(() => {
|
||||
// First, create a map of transcription messages by message ID
|
||||
const transcriptionMessages = new Map(
|
||||
subtitles
|
||||
.filter(s => s.isTranscription)
|
||||
.map(s => [ s.id, s ])
|
||||
);
|
||||
|
||||
if (!selectedLanguage) {
|
||||
// When no language is selected, show all original transcriptions
|
||||
return Array.from(transcriptionMessages.values());
|
||||
}
|
||||
|
||||
// Then, create a map of translation messages by message ID
|
||||
const translationMessages = new Map(
|
||||
subtitles
|
||||
.filter(s => !s.isTranscription && s.language === selectedLanguage)
|
||||
.map(s => [ s.id, s ])
|
||||
);
|
||||
|
||||
// When a language is selected, for each transcription message:
|
||||
// 1. Use its translation if available
|
||||
// 2. Fall back to the original transcription if no translation exists
|
||||
return Array.from(transcriptionMessages.values())
|
||||
.filter((m: ISubtitle) => !m.interim)
|
||||
.map(m => translationMessages.get(m.id) ?? m);
|
||||
}, [ subtitles, selectedLanguage ]);
|
||||
|
||||
const groupedSubtitles = useMemo(() =>
|
||||
groupMessagesBySender(filteredSubtitles), [ filteredSubtitles ]);
|
||||
|
||||
const startClosedCaptions = useCallback(() => {
|
||||
if (isAsyncTranscriptionEnabled) {
|
||||
dispatch(openDialog('StartRecordingDialog', StartRecordingDialog, {
|
||||
recordAudioAndVideo: false
|
||||
}));
|
||||
} else {
|
||||
if (isButtonPressed) {
|
||||
return;
|
||||
}
|
||||
dispatch(setRequestingSubtitles(true, false, null));
|
||||
setButtonPressed(true);
|
||||
}
|
||||
|
||||
}, [ isAsyncTranscriptionEnabled, dispatch, isButtonPressed, openDialog, setButtonPressed ]);
|
||||
|
||||
useEffect(() => {
|
||||
if (subtitlesError && isButtonPressed && !isAsyncTranscriptionEnabled) {
|
||||
setButtonPressed(false);
|
||||
}
|
||||
}, [ subtitlesError, isButtonPressed, isAsyncTranscriptionEnabled ]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!_isTranscribing && isButtonPressed && !isAsyncTranscriptionEnabled) {
|
||||
setButtonPressed(false);
|
||||
}
|
||||
}, [ _isTranscribing, isButtonPressed, isAsyncTranscriptionEnabled ]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isButtonPressed && !isAsyncTranscriptionEnabled) {
|
||||
setButtonPressed(false);
|
||||
}
|
||||
}, [ isButtonPressed, isAsyncTranscriptionEnabled ]);
|
||||
|
||||
return (
|
||||
<Component
|
||||
canStartSubtitles = { _canStartSubtitles }
|
||||
filteredSubtitles = { filteredSubtitles }
|
||||
groupedSubtitles = { groupedSubtitles }
|
||||
isButtonPressed = { isButtonPressed }
|
||||
isTranscribing = { _isTranscribing }
|
||||
startClosedCaptions = { startClosedCaptions } />
|
||||
);
|
||||
};
|
||||
|
||||
export default AbstractClosedCaptions;
|
||||
|
||||
@@ -1,29 +1,39 @@
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
import { Route, useIsFocused } from '@react-navigation/native';
|
||||
import React, { Component, useEffect } from 'react';
|
||||
import { connect, useSelector } from 'react-redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import JitsiScreen from '../../../base/modal/components/JitsiScreen';
|
||||
import { StyleType } from '../../../base/styles/functions.native';
|
||||
import { TabBarLabelCounter } from '../../../mobile/navigation/components/TabBarLabelCounter';
|
||||
import { pollsStyles } from '../../../polls/components/native/styles';
|
||||
import { getUnreadPollCount } from '../../../polls/functions';
|
||||
import { closeChat, sendMessage } from '../../actions.native';
|
||||
import { ChatTabs } from '../../constants';
|
||||
import { getUnreadFilesCount } from '../../functions';
|
||||
import { IChatProps as AbstractProps } from '../../types';
|
||||
|
||||
import ChatInputBar from './ChatInputBar';
|
||||
import MessageContainer from './MessageContainer';
|
||||
import MessageRecipient from './MessageRecipient';
|
||||
import styles from './styles';
|
||||
|
||||
interface IProps extends AbstractProps {
|
||||
|
||||
/**
|
||||
* The number of unread file messages.
|
||||
*/
|
||||
_unreadFilesCount: number;
|
||||
|
||||
/**
|
||||
* The number of unread messages.
|
||||
*/
|
||||
_unreadMessagesCount: number;
|
||||
|
||||
/**
|
||||
* The number of unread polls.
|
||||
*/
|
||||
_unreadPollsCount: number;
|
||||
|
||||
/**
|
||||
* Default prop for navigating between screen components(React Navigation).
|
||||
*/
|
||||
@@ -52,7 +62,6 @@ class Chat extends Component<IProps> {
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
this._onSendMessage = this._onSendMessage.bind(this);
|
||||
this._renderFooter = this._renderFooter.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,10 +76,14 @@ class Chat extends Component<IProps> {
|
||||
return (
|
||||
<JitsiScreen
|
||||
disableForcedKeyboardDismiss = { true }
|
||||
footerComponent = { this._renderFooter }
|
||||
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
footerComponent = { () =>
|
||||
<ChatInputBar onSend = { this._onSendMessage } />
|
||||
}
|
||||
hasBottomTextInput = { true }
|
||||
hasExtraHeaderHeight = { true }
|
||||
style = { pollsStyles.pollPaneContainer as StyleType }>
|
||||
style = { styles.chatContainer }>
|
||||
{/* @ts-ignore */}
|
||||
<MessageContainer messages = { _messages } />
|
||||
<MessageRecipient privateMessageRecipient = { privateMessageRecipient } />
|
||||
@@ -78,16 +91,6 @@ class Chat extends Component<IProps> {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the footer component.
|
||||
*
|
||||
* @private
|
||||
* @returns {React$Element<*>}
|
||||
*/
|
||||
_renderFooter() {
|
||||
return <ChatInputBar onSend = { this._onSendMessage } />;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a text message.
|
||||
*
|
||||
@@ -110,7 +113,9 @@ class Chat extends Component<IProps> {
|
||||
* @private
|
||||
* @returns {{
|
||||
* _messages: Array<Object>,
|
||||
* _unreadMessagesCount: number
|
||||
* _unreadMessagesCount: number,
|
||||
* _unreadPollsCount: number,
|
||||
* _unreadFilesCount: number
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state: IReduxState, _ownProps: any) {
|
||||
@@ -118,34 +123,34 @@ function _mapStateToProps(state: IReduxState, _ownProps: any) {
|
||||
|
||||
return {
|
||||
_messages: messages,
|
||||
_unreadMessagesCount: unreadMessagesCount
|
||||
_unreadMessagesCount: unreadMessagesCount,
|
||||
_unreadPollsCount: getUnreadPollCount(state),
|
||||
_unreadFilesCount: getUnreadFilesCount(state)
|
||||
};
|
||||
}
|
||||
|
||||
export default translate(connect(_mapStateToProps)((props: IProps) => {
|
||||
const { _unreadMessagesCount, dispatch, navigation, t } = props;
|
||||
|
||||
const isChatTabFocused = useSelector((state: IReduxState) => state['features/chat'].focusedTab === ChatTabs.CHAT);
|
||||
const { _unreadMessagesCount, _unreadPollsCount, _unreadFilesCount, dispatch, navigation, t } = props;
|
||||
const totalUnread = _unreadMessagesCount + _unreadPollsCount + _unreadFilesCount;
|
||||
const unreadMessagesNr = totalUnread > 0;
|
||||
|
||||
const isFocused = useIsFocused();
|
||||
|
||||
const activeUnreadMessagesNr = !isChatTabFocused && _unreadMessagesCount > 0;
|
||||
|
||||
useEffect(() => {
|
||||
navigation?.setOptions({
|
||||
tabBarLabel: () => (
|
||||
<TabBarLabelCounter
|
||||
activeUnreadNr = { activeUnreadMessagesNr }
|
||||
activeUnreadNr = { unreadMessagesNr }
|
||||
isFocused = { isFocused }
|
||||
label = { t('chat.tabs.chat') }
|
||||
unreadCount = { _unreadMessagesCount } />
|
||||
unreadCount = { totalUnread } />
|
||||
)
|
||||
});
|
||||
|
||||
return () => {
|
||||
isFocused && dispatch(closeChat());
|
||||
};
|
||||
}, [ isFocused, _unreadMessagesCount ]);
|
||||
}, [ isFocused, _unreadMessagesCount, _unreadPollsCount, _unreadFilesCount ]);
|
||||
|
||||
return (
|
||||
<Chat { ...props } />
|
||||
|
||||
@@ -43,7 +43,7 @@ class ChatButton extends AbstractButton<IProps> {
|
||||
override _handleClick() {
|
||||
this.props._isPollsDisabled
|
||||
? navigate(screen.conference.chat)
|
||||
: navigate(screen.conference.chatTabs.main);
|
||||
: navigate(screen.conference.chatandpolls.main);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@ import { connect } from 'react-redux';
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import { IconSend } from '../../../base/icons/svg';
|
||||
import { ASPECT_RATIO_WIDE } from '../../../base/responsive-ui/constants';
|
||||
import IconButton from '../../../base/ui/components/native/IconButton';
|
||||
import Input from '../../../base/ui/components/native/Input';
|
||||
import { BUTTON_TYPES } from '../../../base/ui/constants.native';
|
||||
@@ -84,6 +85,14 @@ class ChatInputBar extends Component<IProps, IState> {
|
||||
* @inheritdoc
|
||||
*/
|
||||
override render() {
|
||||
let inputBarStyles;
|
||||
|
||||
if (this.props.aspectRatio === ASPECT_RATIO_WIDE) {
|
||||
inputBarStyles = styles.inputBarWide;
|
||||
} else {
|
||||
inputBarStyles = styles.inputBarNarrow;
|
||||
}
|
||||
|
||||
if (this.props._isSendGroupChatDisabled && !this.props._privateMessageRecipientId) {
|
||||
return (
|
||||
<View
|
||||
@@ -100,7 +109,7 @@ class ChatInputBar extends Component<IProps, IState> {
|
||||
<View
|
||||
id = 'chat-input'
|
||||
style = { [
|
||||
styles.inputBar,
|
||||
inputBarStyles,
|
||||
this.state.addPadding ? styles.extraBarPadding : null
|
||||
] as ViewStyle[] }>
|
||||
<Input
|
||||
@@ -120,7 +129,6 @@ class ChatInputBar extends Component<IProps, IState> {
|
||||
id = { this.props.t('chat.sendButton') }
|
||||
onPress = { this._onSubmit }
|
||||
src = { IconSend }
|
||||
style = { styles.sendButton }
|
||||
type = { BUTTON_TYPES.PRIMARY } />
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { TouchableHighlight, View, ViewStyle } from 'react-native';
|
||||
import { Text } from 'react-native-paper';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconArrowRight, IconSubtitles } from '../../../base/icons/svg';
|
||||
import JitsiScreen from '../../../base/modal/components/JitsiScreen';
|
||||
import { StyleType } from '../../../base/styles/functions.any';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
|
||||
import Button from '../../../base/ui/components/native/Button';
|
||||
import { BUTTON_TYPES } from '../../../base/ui/constants.native';
|
||||
import { TabBarLabelCounter } from '../../../mobile/navigation/components/TabBarLabelCounter';
|
||||
import { navigate } from '../../../mobile/navigation/components/conference/ConferenceNavigationContainerRef';
|
||||
import { screen } from '../../../mobile/navigation/routes';
|
||||
import { ChatTabs } from '../../constants';
|
||||
import AbstractClosedCaptions, { AbstractProps } from '../AbstractClosedCaptions';
|
||||
|
||||
import { SubtitlesMessagesContainer } from './SubtitlesMessagesContainer';
|
||||
import { closedCaptionsStyles } from './styles';
|
||||
|
||||
/**
|
||||
* Component that displays the closed captions interface.
|
||||
*
|
||||
* @returns {JSX.Element} - The ClosedCaptions component.
|
||||
*/
|
||||
const ClosedCaptions = ({
|
||||
canStartSubtitles,
|
||||
filteredSubtitles,
|
||||
groupedSubtitles,
|
||||
isButtonPressed,
|
||||
isTranscribing,
|
||||
startClosedCaptions
|
||||
}: AbstractProps): JSX.Element => {
|
||||
const navigation = useNavigation();
|
||||
const { t } = useTranslation();
|
||||
const isCCTabFocused = useSelector((state: IReduxState) => state['features/chat'].focusedTab === ChatTabs.CLOSED_CAPTIONS);
|
||||
const selectedLanguage = useSelector((state: IReduxState) => state['features/subtitles']._language);
|
||||
const navigateToLanguageSelect = useCallback(() => {
|
||||
navigate(screen.conference.subtitles);
|
||||
}, [ navigation, screen ]);
|
||||
const isAsyncTranscriptionEnabled = useSelector((state: IReduxState) =>
|
||||
state['features/base/conference'].conference?.getMetadataHandler()?.getMetadata()?.asyncTranscription);
|
||||
|
||||
useEffect(() => {
|
||||
navigation?.setOptions({
|
||||
tabBarLabel: () => (
|
||||
<TabBarLabelCounter
|
||||
isFocused = { isCCTabFocused }
|
||||
label = { t('chat.tabs.closedCaptions') } />
|
||||
)
|
||||
});
|
||||
}, [ isCCTabFocused, navigation, t ]);
|
||||
|
||||
const getContentContainerStyle = () => {
|
||||
if (isTranscribing) {
|
||||
return closedCaptionsStyles.transcribingContainer as StyleType;
|
||||
}
|
||||
|
||||
return closedCaptionsStyles.emptyContentContainer as StyleType;
|
||||
};
|
||||
|
||||
const renderContent = () => {
|
||||
if (!isTranscribing) {
|
||||
if (canStartSubtitles) {
|
||||
return (
|
||||
<View style = { closedCaptionsStyles.emptyContent as ViewStyle }>
|
||||
<Button
|
||||
accessibilityLabel = { t('closedCaptionsTab.startClosedCaptionsButton') }
|
||||
disabled = { isButtonPressed }
|
||||
labelKey = 'closedCaptionsTab.startClosedCaptionsButton'
|
||||
onClick = { startClosedCaptions }
|
||||
type = { BUTTON_TYPES.PRIMARY } />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style = { closedCaptionsStyles.emptyContent as ViewStyle }>
|
||||
<Icon
|
||||
color = { BaseTheme.palette.icon03 }
|
||||
size = { 100 }
|
||||
src = { IconSubtitles } />
|
||||
<Text style = { [ closedCaptionsStyles.emptyStateText, { marginTop: BaseTheme.spacing[3] } ] }>
|
||||
{ t('closedCaptionsTab.emptyState') }
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{
|
||||
// Hide the "Translate to" option when asyncTranscription is enabled
|
||||
!isAsyncTranscriptionEnabled && <View style = { closedCaptionsStyles.languageButtonContainer as ViewStyle }>
|
||||
<Text style = { closedCaptionsStyles.languageButtonText }>{ t('transcribing.translateTo') }:</Text>
|
||||
<TouchableHighlight onPress = { navigateToLanguageSelect }>
|
||||
<View style = { closedCaptionsStyles.languageButtonContent as ViewStyle }>
|
||||
<Text style = { closedCaptionsStyles.languageButtonText }>{ t(selectedLanguage ?? 'transcribing.subtitlesOff') }</Text>
|
||||
<Icon
|
||||
size = { 24 }
|
||||
src = { IconArrowRight } />
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
}
|
||||
<View style = { closedCaptionsStyles.messagesContainer as ViewStyle }>
|
||||
<SubtitlesMessagesContainer
|
||||
groups = { groupedSubtitles }
|
||||
messages = { filteredSubtitles } />
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<JitsiScreen
|
||||
contentContainerStyle = { getContentContainerStyle() }
|
||||
disableForcedKeyboardDismiss = { true }
|
||||
hasExtraHeaderHeight = { true }
|
||||
style = { closedCaptionsStyles.container as StyleType }>
|
||||
{ renderContent() }
|
||||
</JitsiScreen>
|
||||
);
|
||||
};
|
||||
|
||||
export default AbstractClosedCaptions(ClosedCaptions);
|
||||
@@ -44,23 +44,19 @@ class MessageContainer extends Component<IProps, any> {
|
||||
*/
|
||||
override render() {
|
||||
const data = this._getMessagesGroupedBySender();
|
||||
const noMessages = data.length === 0;
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
ListEmptyComponent = { this._renderListEmptyComponent }
|
||||
bounces = { false }
|
||||
|
||||
// @ts-ignore
|
||||
contentContainerStyle = { noMessages && styles.emptyListContentContainer }
|
||||
data = { data }
|
||||
|
||||
// Workaround for RN bug:
|
||||
// https://github.com/facebook/react-native/issues/21196
|
||||
inverted = { Boolean(data.length) }
|
||||
keyExtractor = { this._keyExtractor }
|
||||
keyboardShouldPersistTaps = 'handled'
|
||||
renderItem = { this._renderMessageGroup }
|
||||
style = { noMessages && styles.emptyListStyle } />
|
||||
renderItem = { this._renderMessageGroup } />
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,8 +67,8 @@ class PrivateMessageButton extends AbstractButton<IProps, any> {
|
||||
? navigate(screen.conference.chat, {
|
||||
privateMessageRecipient: this.props._participant
|
||||
})
|
||||
: navigate(screen.conference.chatTabs.main, {
|
||||
screen: screen.conference.chatTabs.tab.chat,
|
||||
: navigate(screen.conference.chatandpolls.main, {
|
||||
screen: screen.conference.chatandpolls.tab.chat,
|
||||
params: {
|
||||
privateMessageRecipient: this.props._participant
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Text, View, ViewStyle } from 'react-native';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { getParticipantDisplayName } from '../../../base/participants/functions';
|
||||
import { ISubtitle } from '../../../subtitles/types';
|
||||
|
||||
import { closedCaptionsStyles } from './styles';
|
||||
|
||||
|
||||
interface IProps extends ISubtitle {
|
||||
showDisplayName: boolean;
|
||||
}
|
||||
|
||||
export default function SubtitleMessage({ participantId, text, timestamp, interim, showDisplayName }: IProps) {
|
||||
const participantName = useSelector((state: IReduxState) =>
|
||||
getParticipantDisplayName(state, participantId));
|
||||
|
||||
const containerStyle: ViewStyle[] = [
|
||||
closedCaptionsStyles.subtitleMessageContainer as ViewStyle
|
||||
];
|
||||
|
||||
if (interim) {
|
||||
containerStyle.push(closedCaptionsStyles.subtitleMessageInterim as ViewStyle);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style = { containerStyle }>
|
||||
<View style = { closedCaptionsStyles.subtitleMessageContent as ViewStyle }>
|
||||
{
|
||||
showDisplayName && (
|
||||
<Text style = { closedCaptionsStyles.subtitleMessageHeader }>
|
||||
{ participantName }
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
<Text style = { closedCaptionsStyles.subtitleMessageText }>{ text }</Text>
|
||||
<Text style = { closedCaptionsStyles.subtitleMessageTimestamp }>
|
||||
{ new Date(timestamp).toLocaleTimeString() }
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import React from 'react';
|
||||
import { View, ViewStyle } from 'react-native';
|
||||
|
||||
import Avatar from '../../../base/avatar/components/Avatar';
|
||||
import { ISubtitle } from '../../../subtitles/types';
|
||||
|
||||
import SubtitleMessage from './SubtitleMessage';
|
||||
import { closedCaptionsStyles } from './styles';
|
||||
|
||||
|
||||
interface IProps {
|
||||
messages: ISubtitle[];
|
||||
senderId: string;
|
||||
}
|
||||
|
||||
export function SubtitlesGroup({ messages, senderId }: IProps) {
|
||||
if (!messages.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style = { closedCaptionsStyles.subtitlesGroupContainer as ViewStyle }>
|
||||
<View style = { closedCaptionsStyles.subtitlesGroupAvatar as ViewStyle }>
|
||||
<Avatar
|
||||
participantId = { senderId }
|
||||
size = { 32 } />
|
||||
</View>
|
||||
<View style = { closedCaptionsStyles.subtitlesGroupMessagesContainer as ViewStyle }>
|
||||
{
|
||||
messages.map((message, index) => (
|
||||
<SubtitleMessage
|
||||
key = { `${message.timestamp}-${message.id}` }
|
||||
showDisplayName = { index === 0 }
|
||||
{ ...message } />
|
||||
))
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { NativeScrollEvent, NativeSyntheticEvent, ScrollView, View, ViewStyle } from 'react-native';
|
||||
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconArrowDown } from '../../../base/icons/svg';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
|
||||
import Button from '../../../base/ui/components/native/Button';
|
||||
import { BUTTON_TYPES } from '../../../base/ui/constants.native';
|
||||
import { ISubtitle } from '../../../subtitles/types';
|
||||
|
||||
import { SubtitlesGroup } from './SubtitlesGroup';
|
||||
import { closedCaptionsStyles } from './styles';
|
||||
|
||||
/**
|
||||
* The threshold value used to determine if the user is at the bottom of the scroll view.
|
||||
*/
|
||||
const SCROLL_THRESHOLD = 50;
|
||||
|
||||
interface IProps {
|
||||
groups: Array<{
|
||||
messages: ISubtitle[];
|
||||
senderId: string;
|
||||
}>;
|
||||
messages: ISubtitle[];
|
||||
}
|
||||
|
||||
export function SubtitlesMessagesContainer({ messages, groups }: IProps) {
|
||||
const [ hasNewMessages, setHasNewMessages ] = useState(false);
|
||||
const [ isScrolledToBottom, setIsScrolledToBottom ] = useState(true);
|
||||
const scrollViewRef = useRef<ScrollView>(null);
|
||||
const previousMessages = useRef(messages);
|
||||
|
||||
const scrollToBottom = useCallback((withAnimation: boolean) => {
|
||||
scrollViewRef.current?.scrollToEnd({ animated: withAnimation });
|
||||
}, []);
|
||||
|
||||
const handleNewMessagesClick = useCallback(() => {
|
||||
scrollToBottom(true);
|
||||
}, [ scrollToBottom ]);
|
||||
|
||||
const handleScroll = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||
const { contentOffset, contentSize, layoutMeasurement } = event.nativeEvent;
|
||||
const isAtBottom = contentOffset.y + layoutMeasurement.height >= contentSize.height - SCROLL_THRESHOLD;
|
||||
|
||||
setIsScrolledToBottom(isAtBottom);
|
||||
if (isAtBottom) {
|
||||
setHasNewMessages(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
scrollToBottom(false);
|
||||
}, [ scrollToBottom ]);
|
||||
|
||||
useEffect(() => {
|
||||
const newMessages = messages.filter(message => !previousMessages.current.includes(message));
|
||||
|
||||
if (newMessages.length > 0) {
|
||||
if (isScrolledToBottom) {
|
||||
scrollToBottom(false);
|
||||
} else {
|
||||
setHasNewMessages(true);
|
||||
}
|
||||
}
|
||||
|
||||
previousMessages.current = messages;
|
||||
}, [ messages, scrollToBottom ]);
|
||||
|
||||
return (
|
||||
<View style = { closedCaptionsStyles.subtitlesMessagesContainer as ViewStyle }>
|
||||
<ScrollView
|
||||
contentContainerStyle = { closedCaptionsStyles.subtitlesMessagesList as ViewStyle }
|
||||
onScroll = { handleScroll }
|
||||
ref = { scrollViewRef }
|
||||
scrollEventThrottle = { 16 }>
|
||||
{
|
||||
groups.map(group => (
|
||||
<SubtitlesGroup
|
||||
key = { `${group.senderId}-${group.messages[0]?.timestamp}` }
|
||||
messages = { group.messages }
|
||||
senderId = { group.senderId } />
|
||||
))
|
||||
}
|
||||
</ScrollView>
|
||||
{
|
||||
!isScrolledToBottom && hasNewMessages && (
|
||||
<View style = { closedCaptionsStyles.newMessagesButtonContainer as ViewStyle }>
|
||||
<Button
|
||||
accessibilityLabel = 'chat.newMessages'
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
icon = { () => (
|
||||
<Icon
|
||||
color = { BaseTheme.palette.icon04 }
|
||||
size = { 20 }
|
||||
src = { IconArrowDown } />
|
||||
) }
|
||||
labelKey = 'chat.newMessages'
|
||||
onClick = { handleNewMessagesClick }
|
||||
type = { BUTTON_TYPES.SECONDARY } />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -14,6 +14,12 @@ const recipientContainer = {
|
||||
padding: BaseTheme.spacing[2]
|
||||
};
|
||||
|
||||
const inputBar = {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between'
|
||||
};
|
||||
|
||||
/**
|
||||
* The styles of the feature chat.
|
||||
*
|
||||
@@ -38,8 +44,7 @@ export default {
|
||||
},
|
||||
|
||||
emptyComponentText: {
|
||||
...BaseTheme.typography.bodyLongBold,
|
||||
color: BaseTheme.palette.text02,
|
||||
color: BaseTheme.palette.text03,
|
||||
textAlign: 'center'
|
||||
},
|
||||
|
||||
@@ -108,20 +113,11 @@ export default {
|
||||
},
|
||||
|
||||
emptyComponentWrapper: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: BoxModel.padding,
|
||||
maxWidth: '80%'
|
||||
},
|
||||
|
||||
emptyListStyle: {
|
||||
flex: 1
|
||||
},
|
||||
|
||||
emptyListContentContainer: {
|
||||
alignItems: 'center',
|
||||
alignSelf: 'center',
|
||||
flex: 1,
|
||||
justifyContent: 'center'
|
||||
padding: BoxModel.padding,
|
||||
paddingTop: '8%',
|
||||
maxWidth: '80%'
|
||||
},
|
||||
|
||||
disabledSendWrapper: {
|
||||
@@ -137,23 +133,23 @@ export default {
|
||||
* A special padding to avoid issues on some devices (such as Android devices with custom suggestions bar).
|
||||
*/
|
||||
extraBarPadding: {
|
||||
paddingBottom: BaseTheme.spacing[8]
|
||||
paddingBottom: 30
|
||||
},
|
||||
|
||||
inputBar: {
|
||||
alignSelf: 'stretch',
|
||||
flexDirection: 'row',
|
||||
width: '100%'
|
||||
inputBarNarrow: {
|
||||
...inputBar,
|
||||
height: 112,
|
||||
marginHorizontal: BaseTheme.spacing[3]
|
||||
},
|
||||
|
||||
sendButton: {
|
||||
marginRight: BaseTheme.spacing[5],
|
||||
marginLeft: BaseTheme.spacing[2]
|
||||
inputBarWide: {
|
||||
...inputBar,
|
||||
height: 88,
|
||||
marginHorizontal: BaseTheme.spacing[9]
|
||||
},
|
||||
|
||||
customInputContainer: {
|
||||
marginLeft: BaseTheme.spacing[5],
|
||||
flex: 1
|
||||
width: '75%'
|
||||
},
|
||||
|
||||
messageBubble: {
|
||||
@@ -209,6 +205,11 @@ export default {
|
||||
fontSize: 13
|
||||
},
|
||||
|
||||
chatContainer: {
|
||||
backgroundColor: BaseTheme.palette.ui01,
|
||||
flex: 1
|
||||
},
|
||||
|
||||
tabContainer: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center'
|
||||
@@ -269,128 +270,3 @@ export default {
|
||||
flex: 1
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Styles for the ClosedCaptions component.
|
||||
*/
|
||||
export const closedCaptionsStyles = {
|
||||
container: {
|
||||
backgroundColor: BaseTheme.palette.ui01,
|
||||
flex: 1
|
||||
},
|
||||
|
||||
emptyContentContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
|
||||
emptyContent: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flex: 1,
|
||||
padding: BaseTheme.spacing[3]
|
||||
},
|
||||
|
||||
emptyStateText: {
|
||||
...BaseTheme.typography.bodyLongBold,
|
||||
color: BaseTheme.palette.text02,
|
||||
textAlign: 'center',
|
||||
maxWidth: '80%'
|
||||
},
|
||||
|
||||
transcribingContainer: {
|
||||
flex: 1
|
||||
},
|
||||
|
||||
languageButtonContainer: {
|
||||
justifyContent: 'space-between',
|
||||
flexDirection: 'row',
|
||||
padding: BaseTheme.spacing[3]
|
||||
},
|
||||
|
||||
languageButtonText: {
|
||||
...BaseTheme.typography.bodyShortRegularLarge,
|
||||
color: BaseTheme.palette.text01,
|
||||
marginHorizontal: BaseTheme.spacing[2]
|
||||
},
|
||||
|
||||
languageButtonContent: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
|
||||
subtitleMessageContainer: {
|
||||
backgroundColor: BaseTheme.palette.ui02,
|
||||
borderRadius: BaseTheme.shape.borderRadius,
|
||||
padding: BaseTheme.spacing[2],
|
||||
maxWidth: '100%',
|
||||
marginTop: BaseTheme.spacing[1]
|
||||
},
|
||||
|
||||
subtitleMessageContent: {
|
||||
maxWidth: '100%',
|
||||
flex: 1
|
||||
},
|
||||
|
||||
subtitleMessageHeader: {
|
||||
...BaseTheme.typography.labelBold,
|
||||
color: BaseTheme.palette.text02,
|
||||
marginBottom: BaseTheme.spacing[1],
|
||||
maxWidth: 130
|
||||
},
|
||||
|
||||
subtitleMessageText: {
|
||||
...BaseTheme.typography.bodyShortRegular,
|
||||
color: BaseTheme.palette.text01
|
||||
},
|
||||
|
||||
subtitleMessageTimestamp: {
|
||||
...BaseTheme.typography.labelRegular,
|
||||
color: BaseTheme.palette.text03,
|
||||
marginTop: BaseTheme.spacing[1]
|
||||
},
|
||||
|
||||
subtitleMessageInterim: {
|
||||
opacity: 0.7
|
||||
},
|
||||
|
||||
subtitlesGroupContainer: {
|
||||
flexDirection: 'row',
|
||||
marginBottom: BaseTheme.spacing[3]
|
||||
},
|
||||
|
||||
subtitlesGroupAvatar: {
|
||||
marginBottom: BaseTheme.spacing[10],
|
||||
marginRight: BaseTheme.spacing[2],
|
||||
alignSelf: 'flex-start',
|
||||
width: 32
|
||||
},
|
||||
|
||||
subtitlesGroupMessagesContainer: {
|
||||
flexDirection: 'column',
|
||||
flex: 1,
|
||||
maxWidth: '100%'
|
||||
},
|
||||
|
||||
subtitlesMessagesContainer: {
|
||||
flex: 1,
|
||||
position: 'relative',
|
||||
height: '100%'
|
||||
},
|
||||
|
||||
subtitlesMessagesList: {
|
||||
padding: BaseTheme.spacing[4]
|
||||
},
|
||||
|
||||
newMessagesButtonContainer: {
|
||||
position: 'absolute',
|
||||
bottom: BaseTheme.spacing[3],
|
||||
alignSelf: 'center'
|
||||
},
|
||||
|
||||
messagesContainer: {
|
||||
display: 'flex',
|
||||
flex: 1,
|
||||
overflow: 'hidden'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,7 +4,6 @@ import { connect, useSelector } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { isTouchDevice, shouldEnableResize } from '../../../base/environment/utils';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import { IconInfo, IconMessage, IconShareDoc, IconSubtitles } from '../../../base/icons/svg';
|
||||
import { getLocalParticipant, getRemoteParticipants, isPrivateChatEnabledSelf } from '../../../base/participants/functions';
|
||||
@@ -24,16 +23,7 @@ import {
|
||||
setUserChatWidth,
|
||||
toggleChat
|
||||
} from '../../actions.web';
|
||||
import {
|
||||
CHAT_DRAG_HANDLE_HEIGHT,
|
||||
CHAT_DRAG_HANDLE_OFFSET,
|
||||
CHAT_DRAG_HANDLE_WIDTH,
|
||||
CHAT_SIZE,
|
||||
CHAT_TOUCH_HANDLE_SIZE,
|
||||
ChatTabs,
|
||||
OPTION_GROUPCHAT,
|
||||
SMALL_WIDTH_THRESHOLD
|
||||
} from '../../constants';
|
||||
import { CHAT_SIZE, ChatTabs, OPTION_GROUPCHAT, SMALL_WIDTH_THRESHOLD } from '../../constants';
|
||||
import { getChatMaxSize, getFocusedTab, isChatDisabled } from '../../functions';
|
||||
import { IChatProps as AbstractProps } from '../../types';
|
||||
|
||||
@@ -114,15 +104,10 @@ interface IProps extends AbstractProps {
|
||||
_width: number;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles<{
|
||||
_isResizing: boolean;
|
||||
isTouch: boolean;
|
||||
resizeEnabled: boolean;
|
||||
width: number;
|
||||
}>()((theme, { _isResizing, isTouch, resizeEnabled, width }) => {
|
||||
const useStyles = makeStyles<{ _isResizing: boolean; width: number; }>()((theme, { _isResizing, width }) => {
|
||||
return {
|
||||
container: {
|
||||
backgroundColor: theme.palette.chatBackground,
|
||||
backgroundColor: theme.palette.ui01,
|
||||
flexShrink: 0,
|
||||
overflow: 'hidden',
|
||||
position: 'relative',
|
||||
@@ -130,15 +115,11 @@ const useStyles = makeStyles<{
|
||||
width: `${width}px`,
|
||||
zIndex: 300,
|
||||
|
||||
// On non-touch devices (desktop), show handle on hover
|
||||
// On touch devices, handle is always visible if resize is enabled
|
||||
...(!isTouch && {
|
||||
'&:hover, &:focus-within': {
|
||||
'& .dragHandleContainer': {
|
||||
visibility: 'visible'
|
||||
}
|
||||
'&:hover, &:focus-within': {
|
||||
'& .dragHandleContainer': {
|
||||
visibility: 'visible'
|
||||
}
|
||||
}),
|
||||
},
|
||||
|
||||
'@media (max-width: 580px)': {
|
||||
height: '100dvh',
|
||||
@@ -165,7 +146,7 @@ const useStyles = makeStyles<{
|
||||
padding: `${theme.spacing(3)} ${theme.spacing(4)}`,
|
||||
alignItems: 'center',
|
||||
boxSizing: 'border-box',
|
||||
color: theme.palette.chatMessageText,
|
||||
color: theme.palette.text01,
|
||||
...theme.typography.heading6,
|
||||
lineHeight: 'unset',
|
||||
fontWeight: theme.typography.heading6.fontWeight as any,
|
||||
@@ -202,23 +183,16 @@ const useStyles = makeStyles<{
|
||||
|
||||
dragHandleContainer: {
|
||||
height: '100%',
|
||||
// Touch devices need larger hit target but positioned to not take extra space
|
||||
width: isTouch ? `${CHAT_TOUCH_HANDLE_SIZE}px` : `${CHAT_DRAG_HANDLE_WIDTH}px`,
|
||||
width: '9px',
|
||||
backgroundColor: 'transparent',
|
||||
position: 'absolute',
|
||||
cursor: 'col-resize',
|
||||
display: resizeEnabled ? 'flex' : 'none', // Hide if resize not enabled
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
// On touch devices, always visible if resize enabled. On desktop, hidden by default
|
||||
visibility: (isTouch && resizeEnabled) ? 'visible' : 'hidden',
|
||||
// Position touch handle centered on offset from edge, maintaining same gap as non-touch
|
||||
right: isTouch
|
||||
? `${CHAT_DRAG_HANDLE_OFFSET - Math.floor((CHAT_TOUCH_HANDLE_SIZE - CHAT_DRAG_HANDLE_WIDTH) / 2)}px`
|
||||
: `${CHAT_DRAG_HANDLE_OFFSET}px`,
|
||||
visibility: 'hidden',
|
||||
right: '4px',
|
||||
top: 0,
|
||||
// Prevent touch scrolling while dragging
|
||||
touchAction: 'none',
|
||||
|
||||
'&:hover': {
|
||||
'& .dragHandle': {
|
||||
@@ -236,15 +210,10 @@ const useStyles = makeStyles<{
|
||||
},
|
||||
|
||||
dragHandle: {
|
||||
// Keep the same visual appearance on all devices
|
||||
backgroundColor: theme.palette.icon02,
|
||||
height: `${CHAT_DRAG_HANDLE_HEIGHT}px`,
|
||||
width: `${CHAT_DRAG_HANDLE_WIDTH / 3}px`,
|
||||
borderRadius: '1px',
|
||||
// Make more visible when actively shown
|
||||
...(isTouch && resizeEnabled && {
|
||||
backgroundColor: theme.palette.icon01
|
||||
})
|
||||
height: '100px',
|
||||
width: '3px',
|
||||
borderRadius: '1px'
|
||||
},
|
||||
|
||||
privateMessageRecipientsList: {
|
||||
@@ -277,10 +246,7 @@ const Chat = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
// Detect touch capability and screen size for resize functionality
|
||||
const isTouch = isTouchDevice();
|
||||
const resizeEnabled = shouldEnableResize();
|
||||
const { classes, cx } = useStyles({ _isResizing, width: _width, isTouch, resizeEnabled });
|
||||
const { classes, cx } = useStyles({ _isResizing, width: _width });
|
||||
const [ isMouseDown, setIsMouseDown ] = useState(false);
|
||||
const [ mousePosition, setMousePosition ] = useState<number | null>(null);
|
||||
const [ dragChatWidth, setDragChatWidth ] = useState<number | null>(null);
|
||||
@@ -316,21 +282,16 @@ const Chat = ({
|
||||
}, [ participants, defaultRemoteDisplayName, t, notifyTimestamp ]);
|
||||
|
||||
/**
|
||||
* Handles pointer down on the drag handle.
|
||||
* Supports both mouse and touch events via Pointer Events API.
|
||||
* Handles mouse down on the drag handle.
|
||||
*
|
||||
* @param {React.PointerEvent} e - The pointer down event.
|
||||
* @param {MouseEvent} e - The mouse down event.
|
||||
* @returns {void}
|
||||
*/
|
||||
const onDragHandlePointerDown = useCallback((e: React.PointerEvent) => {
|
||||
const onDragHandleMouseDown = useCallback((e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Capture the pointer to ensure we receive all pointer events
|
||||
// even if the pointer moves outside the element
|
||||
(e.target as HTMLElement).setPointerCapture(e.pointerId);
|
||||
|
||||
// Store the initial pointer position and chat width
|
||||
// Store the initial mouse position and chat width
|
||||
setIsMouseDown(true);
|
||||
setMousePosition(e.clientX);
|
||||
setDragChatWidth(_width);
|
||||
@@ -338,7 +299,7 @@ const Chat = ({
|
||||
// Indicate that resizing is in progress
|
||||
dispatch(setChatIsResizing(true));
|
||||
|
||||
// Add visual feedback that we're dragging (cursor for mouse, not visible on touch)
|
||||
// Add visual feedback that we're dragging
|
||||
document.body.style.cursor = 'col-resize';
|
||||
|
||||
// Disable text selection during resize
|
||||
@@ -346,12 +307,11 @@ const Chat = ({
|
||||
}, [ _width, dispatch ]);
|
||||
|
||||
/**
|
||||
* Drag handle pointer up handler.
|
||||
* Supports both mouse and touch events via Pointer Events API.
|
||||
* Drag handle mouse up handler.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
const onDragPointerUp = useCallback(() => {
|
||||
const onDragMouseUp = useCallback(() => {
|
||||
if (isMouseDown) {
|
||||
setIsMouseDown(false);
|
||||
dispatch(setChatIsResizing(false));
|
||||
@@ -363,13 +323,12 @@ const Chat = ({
|
||||
}, [ isMouseDown, dispatch ]);
|
||||
|
||||
/**
|
||||
* Handles drag handle pointer move.
|
||||
* Supports both mouse and touch events via Pointer Events API.
|
||||
* Handles drag handle mouse move.
|
||||
*
|
||||
* @param {PointerEvent} e - The pointermove event.
|
||||
* @param {MouseEvent} e - The mousemove event.
|
||||
* @returns {void}
|
||||
*/
|
||||
const onChatResize = useCallback(throttle((e: PointerEvent) => {
|
||||
const onChatResize = useCallback(throttle((e: MouseEvent) => {
|
||||
if (isMouseDown && mousePosition !== null && dragChatWidth !== null) {
|
||||
// For chat panel resizing on the left edge:
|
||||
// - Dragging left (decreasing X coordinate) should make the panel wider
|
||||
@@ -393,14 +352,14 @@ const Chat = ({
|
||||
|
||||
// Set up event listeners when component mounts
|
||||
useEffect(() => {
|
||||
document.addEventListener('pointerup', onDragPointerUp);
|
||||
document.addEventListener('pointermove', onChatResize);
|
||||
document.addEventListener('mouseup', onDragMouseUp);
|
||||
document.addEventListener('mousemove', onChatResize);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('pointerup', onDragPointerUp);
|
||||
document.removeEventListener('pointermove', onChatResize);
|
||||
document.removeEventListener('mouseup', onDragMouseUp);
|
||||
document.removeEventListener('mousemove', onChatResize);
|
||||
};
|
||||
}, [ onDragPointerUp, onChatResize ]);
|
||||
}, [ onDragMouseUp, onChatResize ]);
|
||||
|
||||
/**
|
||||
* Sends a text message.
|
||||
@@ -641,7 +600,7 @@ const Chat = ({
|
||||
(isMouseDown || _isResizing) && 'visible',
|
||||
'dragHandleContainer'
|
||||
) }
|
||||
onPointerDown = { onDragHandlePointerDown }>
|
||||
onMouseDown = { onDragHandleMouseDown }>
|
||||
<div className = { cx(classes.dragHandle, 'dragHandle') } />
|
||||
</div>
|
||||
</div> : null
|
||||
|
||||
@@ -37,7 +37,7 @@ const styles = (_theme: Theme, { _chatWidth }: IProps) => {
|
||||
}
|
||||
},
|
||||
chatDisabled: {
|
||||
borderTop: `1px solid ${_theme.palette.chatInputBorder}`,
|
||||
borderTop: `1px solid ${_theme.palette.ui02}`,
|
||||
boxSizing: 'border-box' as const,
|
||||
padding: _theme.spacing(4),
|
||||
textAlign: 'center' as const,
|
||||
|
||||
@@ -43,7 +43,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
chatMessage: {
|
||||
display: 'inline-flex',
|
||||
padding: '12px',
|
||||
backgroundColor: theme.palette.chatMessageRemote,
|
||||
backgroundColor: theme.palette.ui02,
|
||||
borderRadius: '4px 12px 12px 12px',
|
||||
maxWidth: '100%',
|
||||
marginTop: '4px',
|
||||
@@ -66,21 +66,21 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
|
||||
'&.privatemessage': {
|
||||
backgroundColor: theme.palette.chatMessagePrivate
|
||||
backgroundColor: theme.palette.support05
|
||||
},
|
||||
'&.local': {
|
||||
backgroundColor: theme.palette.chatMessageLocal,
|
||||
backgroundColor: theme.palette.ui04,
|
||||
borderRadius: '12px 4px 12px 12px',
|
||||
|
||||
'&.privatemessage': {
|
||||
backgroundColor: theme.palette.chatMessagePrivate
|
||||
backgroundColor: theme.palette.support05
|
||||
},
|
||||
'&.local': {
|
||||
backgroundColor: theme.palette.chatMessageLocal,
|
||||
backgroundColor: theme.palette.ui04,
|
||||
borderRadius: '12px 4px 12px 12px',
|
||||
|
||||
'&.privatemessage': {
|
||||
backgroundColor: theme.palette.chatMessagePrivate
|
||||
backgroundColor: theme.palette.support05
|
||||
}
|
||||
},
|
||||
|
||||
@@ -91,7 +91,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
|
||||
'&.lobbymessage': {
|
||||
backgroundColor: theme.palette.chatMessagePrivate
|
||||
backgroundColor: theme.palette.support05
|
||||
}
|
||||
},
|
||||
'&.error': {
|
||||
@@ -100,7 +100,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
fontWeight: 100
|
||||
},
|
||||
'&.lobbymessage': {
|
||||
backgroundColor: theme.palette.chatMessagePrivate
|
||||
backgroundColor: theme.palette.support05
|
||||
}
|
||||
},
|
||||
sideBySideContainer: {
|
||||
@@ -146,7 +146,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
displayName: {
|
||||
...theme.typography.labelBold,
|
||||
color: theme.palette.chatSenderName,
|
||||
color: theme.palette.text02,
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
overflow: 'hidden',
|
||||
@@ -155,18 +155,18 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
userMessage: {
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.chatMessageText,
|
||||
color: theme.palette.text01,
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-word'
|
||||
},
|
||||
privateMessageNotice: {
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.chatPrivateNotice,
|
||||
color: theme.palette.text02,
|
||||
marginTop: theme.spacing(1)
|
||||
},
|
||||
timestamp: {
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.chatTimestamp,
|
||||
color: theme.palette.text03,
|
||||
marginTop: theme.spacing(1),
|
||||
marginLeft: theme.spacing(1),
|
||||
whiteSpace: 'nowrap',
|
||||
@@ -174,12 +174,12 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
reactionsPopover: {
|
||||
padding: theme.spacing(2),
|
||||
backgroundColor: theme.palette.chatInputBackground,
|
||||
backgroundColor: theme.palette.ui03,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
maxWidth: '150px',
|
||||
maxHeight: '400px',
|
||||
overflowY: 'auto',
|
||||
color: theme.palette.chatMessageText
|
||||
color: theme.palette.text01
|
||||
},
|
||||
reactionItem: {
|
||||
display: 'flex',
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
import React from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { openDialog } from '../../../base/dialog/actions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconSubtitles } from '../../../base/icons/svg';
|
||||
import Button from '../../../base/ui/components/web/Button';
|
||||
import { groupMessagesBySender } from '../../../base/util/messageGrouping';
|
||||
import { StartRecordingDialog } from '../../../recording/components/Recording';
|
||||
import { setRequestingSubtitles } from '../../../subtitles/actions.any';
|
||||
import LanguageSelector from '../../../subtitles/components/web/LanguageSelector';
|
||||
// @ts-ignore
|
||||
import AbstractClosedCaptions, { AbstractProps } from '../AbstractClosedCaptions';
|
||||
import { canStartSubtitles } from '../../../subtitles/functions.any';
|
||||
import { ISubtitle } from '../../../subtitles/types';
|
||||
import { isTranscribing } from '../../../transcribing/functions';
|
||||
|
||||
import { SubtitlesMessagesContainer } from './SubtitlesMessagesContainer';
|
||||
|
||||
@@ -24,7 +31,7 @@ const useStyles = makeStyles()(theme => {
|
||||
padding: '16px',
|
||||
flex: 1,
|
||||
boxSizing: 'border-box',
|
||||
color: theme.palette.chatMessageText
|
||||
color: theme.palette.text01
|
||||
},
|
||||
container: {
|
||||
display: 'flex',
|
||||
@@ -48,7 +55,7 @@ const useStyles = makeStyles()(theme => {
|
||||
boxSizing: 'border-box',
|
||||
flexDirection: 'column',
|
||||
gap: '16px',
|
||||
color: theme.palette.chatMessageText,
|
||||
color: theme.palette.text01,
|
||||
textAlign: 'center'
|
||||
},
|
||||
emptyIcon: {
|
||||
@@ -62,7 +69,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
emptyState: {
|
||||
...theme.typography.bodyLongBold,
|
||||
color: theme.palette.chatSenderName
|
||||
color: theme.palette.text02
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -72,19 +79,72 @@ const useStyles = makeStyles()(theme => {
|
||||
*
|
||||
* @returns {JSX.Element} - The ClosedCaptionsTab component.
|
||||
*/
|
||||
const ClosedCaptionsTab = ({
|
||||
canStartSubtitles,
|
||||
filteredSubtitles,
|
||||
groupedSubtitles,
|
||||
isButtonPressed,
|
||||
isTranscribing,
|
||||
startClosedCaptions
|
||||
}: AbstractProps): JSX.Element => {
|
||||
export default function ClosedCaptionsTab() {
|
||||
const { classes, theme } = useStyles();
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
const subtitles = useSelector((state: IReduxState) => state['features/subtitles'].subtitlesHistory);
|
||||
const language = useSelector((state: IReduxState) => state['features/subtitles']._language);
|
||||
const selectedLanguage = language?.replace('translation-languages:', '');
|
||||
const _isTranscribing = useSelector(isTranscribing);
|
||||
const _canStartSubtitles = useSelector(canStartSubtitles);
|
||||
const [ isButtonPressed, setButtonPressed ] = useState(false);
|
||||
const subtitlesError = useSelector((state: IReduxState) => state['features/subtitles']._hasError);
|
||||
const isAsyncTranscriptionEnabled = useSelector((state: IReduxState) =>
|
||||
state['features/base/conference'].conference?.getMetadataHandler()?.getMetadata()?.asyncTranscription);
|
||||
|
||||
if (!isTranscribing) {
|
||||
if (canStartSubtitles) {
|
||||
const filteredSubtitles = useMemo(() => {
|
||||
// First, create a map of transcription messages by message ID
|
||||
const transcriptionMessages = new Map(
|
||||
subtitles
|
||||
.filter(s => s.isTranscription)
|
||||
.map(s => [ s.id, s ])
|
||||
);
|
||||
|
||||
if (!selectedLanguage) {
|
||||
// When no language is selected, show all original transcriptions
|
||||
return Array.from(transcriptionMessages.values());
|
||||
}
|
||||
|
||||
// Then, create a map of translation messages by message ID
|
||||
const translationMessages = new Map(
|
||||
subtitles
|
||||
.filter(s => !s.isTranscription && s.language === selectedLanguage)
|
||||
.map(s => [ s.id, s ])
|
||||
);
|
||||
|
||||
// When a language is selected, for each transcription message:
|
||||
// 1. Use its translation if available
|
||||
// 2. Fall back to the original transcription if no translation exists
|
||||
return Array.from(transcriptionMessages.values())
|
||||
.filter((m: ISubtitle) => !m.interim)
|
||||
.map(m => translationMessages.get(m.id) ?? m);
|
||||
}, [ subtitles, selectedLanguage ]);
|
||||
|
||||
const groupedSubtitles = useMemo(() =>
|
||||
groupMessagesBySender(filteredSubtitles), [ filteredSubtitles ]);
|
||||
|
||||
const startClosedCaptions = useCallback(() => {
|
||||
if (isAsyncTranscriptionEnabled) {
|
||||
dispatch(openDialog('StartRecordingDialog', StartRecordingDialog, {
|
||||
recordAudioAndVideo: false
|
||||
}));
|
||||
} else {
|
||||
if (isButtonPressed) {
|
||||
return;
|
||||
}
|
||||
dispatch(setRequestingSubtitles(true, false, null));
|
||||
setButtonPressed(true);
|
||||
}
|
||||
|
||||
}, [ isAsyncTranscriptionEnabled, dispatch, isButtonPressed, openDialog, setButtonPressed ]);
|
||||
|
||||
if (subtitlesError && isButtonPressed && !isAsyncTranscriptionEnabled) {
|
||||
setButtonPressed(false);
|
||||
}
|
||||
|
||||
if (!_isTranscribing) {
|
||||
if (_canStartSubtitles) {
|
||||
return (
|
||||
<div className = { classes.emptyContent }>
|
||||
<Button
|
||||
@@ -99,11 +159,15 @@ const ClosedCaptionsTab = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (isButtonPressed && !isAsyncTranscriptionEnabled) {
|
||||
setButtonPressed(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className = { classes.emptyContent }>
|
||||
<Icon
|
||||
className = { classes.emptyIcon }
|
||||
color = { theme.palette.chatEmptyText }
|
||||
color = { theme.palette.icon03 }
|
||||
src = { IconSubtitles } />
|
||||
<span className = { classes.emptyState }>
|
||||
{ t('closedCaptionsTab.emptyState') }
|
||||
@@ -112,6 +176,10 @@ const ClosedCaptionsTab = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (isButtonPressed && !isAsyncTranscriptionEnabled) {
|
||||
setButtonPressed(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className = { classes.container }>
|
||||
<LanguageSelector />
|
||||
@@ -122,6 +190,4 @@ const ClosedCaptionsTab = ({
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AbstractClosedCaptions(ClosedCaptionsTab);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
borderRadius: '4px',
|
||||
backgroundColor: theme.palette.chatInputBackground
|
||||
backgroundColor: theme.palette.ui03
|
||||
},
|
||||
|
||||
emojiButton: {
|
||||
|
||||
@@ -46,12 +46,12 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
// Add background to button container to hide text underneath in chat context
|
||||
'& > div:last-child': {
|
||||
backgroundColor: theme.palette.chatMessageRemote,
|
||||
backgroundColor: theme.palette.ui02,
|
||||
paddingLeft: theme.spacing(2)
|
||||
},
|
||||
|
||||
'&:hover > div:last-child': {
|
||||
backgroundColor: theme.palette.chatInputBackground
|
||||
backgroundColor: theme.palette.ui03
|
||||
}
|
||||
},
|
||||
|
||||
@@ -66,7 +66,7 @@ const useStyles = makeStyles()(theme => {
|
||||
deletedFileMessage: {
|
||||
...theme.typography.bodyShortRegular,
|
||||
fontStyle: 'italic',
|
||||
color: theme.palette.fileSharingEmptyText,
|
||||
color: theme.palette.text02,
|
||||
padding: theme.spacing(1, 0)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,14 +39,14 @@ const useStyles = makeStyles()(theme => {
|
||||
}
|
||||
},
|
||||
menuPanel: {
|
||||
backgroundColor: theme.palette.chatInputBackground,
|
||||
backgroundColor: theme.palette.ui03,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
boxShadow: theme.shadows[3],
|
||||
overflow: 'hidden'
|
||||
},
|
||||
copiedMessage: {
|
||||
position: 'fixed',
|
||||
backgroundColor: theme.palette.chatInputBackground,
|
||||
backgroundColor: theme.palette.ui03,
|
||||
color: 'white',
|
||||
padding: '4px 8px',
|
||||
borderRadius: '4px',
|
||||
|
||||
@@ -24,7 +24,7 @@ const useStyles = makeStyles()(theme => {
|
||||
backgroundColor: theme.palette.support05,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.chatRecipientText
|
||||
color: theme.palette.text01
|
||||
},
|
||||
|
||||
text: {
|
||||
|
||||
@@ -22,7 +22,7 @@ interface IProps extends ISubtitle {
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
messageContainer: {
|
||||
backgroundColor: theme.palette.subtitleMessageBackground,
|
||||
backgroundColor: theme.palette.ui02,
|
||||
borderRadius: '4px 12px 12px 12px',
|
||||
padding: '12px',
|
||||
maxWidth: '100%',
|
||||
@@ -39,7 +39,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
messageHeader: {
|
||||
...theme.typography.labelBold,
|
||||
color: theme.palette.subtitleMessageSender,
|
||||
color: theme.palette.text02,
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
overflow: 'hidden',
|
||||
@@ -49,14 +49,14 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
messageText: {
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.subtitleMessageText,
|
||||
color: theme.palette.text01,
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-word'
|
||||
},
|
||||
|
||||
timestamp: {
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.subtitleMessageTime,
|
||||
color: theme.palette.text03,
|
||||
marginTop: theme.spacing(1)
|
||||
},
|
||||
|
||||
|
||||
@@ -33,23 +33,6 @@ export const MESSAGE_TYPE_REMOTE = 'remote';
|
||||
|
||||
export const SMALL_WIDTH_THRESHOLD = 580;
|
||||
|
||||
/**
|
||||
* Drag handle dimensions for resizable chat.
|
||||
*/
|
||||
export const CHAT_DRAG_HANDLE_WIDTH = 9;
|
||||
export const CHAT_DRAG_HANDLE_HEIGHT = 100;
|
||||
|
||||
/**
|
||||
* Touch target size for chat drag handle on touch devices.
|
||||
* Provides adequate hit area (44px) for comfortable tapping.
|
||||
*/
|
||||
export const CHAT_TOUCH_HANDLE_SIZE = 44;
|
||||
|
||||
/**
|
||||
* Offset from edge for positioning the chat drag handle.
|
||||
*/
|
||||
export const CHAT_DRAG_HANDLE_OFFSET = 4;
|
||||
|
||||
|
||||
/**
|
||||
* Lobby message type.
|
||||
|
||||
@@ -21,9 +21,10 @@ const titleBarSafeView = {
|
||||
export default {
|
||||
|
||||
bottomContainer: {
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
bottom: BaseTheme.spacing[8]
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -100,7 +101,7 @@ export default {
|
||||
},
|
||||
|
||||
soundDeviceButton: {
|
||||
marginVertical: BaseTheme.spacing[3],
|
||||
marginBottom: BaseTheme.spacing[3],
|
||||
width: 240
|
||||
},
|
||||
|
||||
@@ -161,6 +162,7 @@ export default {
|
||||
videoStoppedLabel: {
|
||||
...BaseTheme.typography.bodyShortRegularLarge,
|
||||
color: BaseTheme.palette.text01,
|
||||
marginBottom: BaseTheme.spacing[3],
|
||||
textAlign: 'center',
|
||||
width: '100%'
|
||||
},
|
||||
|
||||
@@ -14,7 +14,6 @@ import { setColorAlpha } from '../../../base/util/helpers';
|
||||
import { openChat, setFocusedTab } from '../../../chat/actions.web';
|
||||
import Chat from '../../../chat/components/web/Chat';
|
||||
import { ChatTabs } from '../../../chat/constants';
|
||||
import CustomPanel from '../../../custom-panel/components/web/CustomPanel';
|
||||
import { isFileUploadingEnabled, processFiles } from '../../../file-sharing/functions.any';
|
||||
import MainFilmstrip from '../../../filmstrip/components/web/MainFilmstrip';
|
||||
import ScreenshareFilmstrip from '../../../filmstrip/components/web/ScreenshareFilmstrip';
|
||||
@@ -258,9 +257,6 @@ class Conference extends AbstractConference<IProps, any> {
|
||||
id = 'videospace'
|
||||
onTouchStart = { this._onVideospaceTouchStart }>
|
||||
<LargeVideo />
|
||||
<StageFilmstrip />
|
||||
<ScreenshareFilmstrip />
|
||||
<MainFilmstrip />
|
||||
</div>
|
||||
<span
|
||||
aria-level = { 1 }
|
||||
@@ -327,7 +323,6 @@ class Conference extends AbstractConference<IProps, any> {
|
||||
{ _showVisitorsQueue && <VisitorsQueue />}
|
||||
</div>
|
||||
<ParticipantsPane />
|
||||
<CustomPanel />
|
||||
<ReactionAnimations />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
timer: {
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.conferenceTimerText,
|
||||
color: theme.palette.text01,
|
||||
padding: '6px 8px',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||
boxSizing: 'border-box',
|
||||
|
||||
@@ -15,8 +15,8 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
message: {
|
||||
backgroundColor: theme.palette.conferenceNoticeBackground,
|
||||
color: theme.palette.conferenceNoticeText,
|
||||
backgroundColor: theme.palette.uiBackground,
|
||||
color: theme.palette.text01,
|
||||
padding: '3px',
|
||||
borderRadius: '5px'
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
label: {
|
||||
backgroundColor: theme.palette.warning02,
|
||||
color: theme.palette.conferenceRaisedHandLabelText
|
||||
color: theme.palette.uiBackground
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -35,7 +35,7 @@ const RaisedHandsCountLabel = () => {
|
||||
accessibilityText = { t('raisedHandsLabel') }
|
||||
className = { styles.label }
|
||||
icon = { IconRaiseHand }
|
||||
iconColor = { theme.palette.conferenceRaisedHandLabelIcon }
|
||||
iconColor = { theme.palette.icon04 }
|
||||
id = 'raisedHandsCountLabel'
|
||||
onClick = { onClick }
|
||||
text = { `${raisedHandsCount}` } />
|
||||
|
||||
@@ -10,7 +10,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
container: {
|
||||
...theme.typography.bodyLongRegular,
|
||||
color: theme.palette.conferenceSubjectText,
|
||||
color: theme.palette.text01,
|
||||
padding: '2px 16px',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.6)',
|
||||
maxWidth: '324px',
|
||||
|
||||
@@ -14,13 +14,13 @@ import Input from '../../../base/ui/components/web/Input';
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
content: {
|
||||
color: theme.palette.dialogText
|
||||
color: theme.palette.text01
|
||||
},
|
||||
|
||||
info: {
|
||||
background: theme.palette.dialogBackground,
|
||||
background: theme.palette.ui01,
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.dialogSecondaryText,
|
||||
color: theme.palette.text02,
|
||||
marginTop: theme.spacing(2)
|
||||
},
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ const styles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'&.status-lost': {
|
||||
backgroundColor: theme.palette.connectionIndicatorLost
|
||||
backgroundColor: theme.palette.ui05
|
||||
},
|
||||
|
||||
'&.status-other': {
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* Action type to signal the closing of the custom panel.
|
||||
*/
|
||||
export const CUSTOM_PANEL_CLOSE = 'CUSTOM_PANEL_CLOSE';
|
||||
|
||||
/**
|
||||
* Action type to signal the opening of the custom panel.
|
||||
*/
|
||||
export const CUSTOM_PANEL_OPEN = 'CUSTOM_PANEL_OPEN';
|
||||
|
||||
/**
|
||||
* Action type to enable or disable the custom panel dynamically.
|
||||
*/
|
||||
export const SET_CUSTOM_PANEL_ENABLED = 'SET_CUSTOM_PANEL_ENABLED';
|
||||
@@ -1,40 +0,0 @@
|
||||
import {
|
||||
CUSTOM_PANEL_CLOSE,
|
||||
CUSTOM_PANEL_OPEN,
|
||||
SET_CUSTOM_PANEL_ENABLED
|
||||
} from './actionTypes';
|
||||
|
||||
/**
|
||||
* Action to close the custom panel.
|
||||
*
|
||||
* @returns {Object} The action object.
|
||||
*/
|
||||
export function close() {
|
||||
return {
|
||||
type: CUSTOM_PANEL_CLOSE
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to open the custom panel.
|
||||
*
|
||||
* @returns {Object} The action object.
|
||||
*/
|
||||
export function open() {
|
||||
return {
|
||||
type: CUSTOM_PANEL_OPEN
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to enable or disable the custom panel dynamically.
|
||||
*
|
||||
* @param {boolean} enabled - Whether the custom panel should be enabled.
|
||||
* @returns {Object} The action object.
|
||||
*/
|
||||
export function setCustomPanelEnabled(enabled: boolean) {
|
||||
return {
|
||||
type: SET_CUSTOM_PANEL_ENABLED,
|
||||
enabled
|
||||
};
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Custom panel placeholder component.
|
||||
* This file is overridden by jitsi-meet-branding at build time
|
||||
* to provide the actual panel implementation with iframe content.
|
||||
*
|
||||
* @returns {null} This placeholder renders nothing.
|
||||
*/
|
||||
const CustomPanel = (): null => null;
|
||||
|
||||
export default CustomPanel;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user