mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-02-08 06:50:17 +00:00
Compare commits
17 Commits
debug-test
...
9028
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ab86cffb8 | ||
|
|
9ea9f4c899 | ||
|
|
28c72bfa7f | ||
|
|
24c78cf8ff | ||
|
|
147e64106d | ||
|
|
3d53f2e4c5 | ||
|
|
e60bfc573a | ||
|
|
796a7efa7f | ||
|
|
fb075c376d | ||
|
|
c457ed0d3c | ||
|
|
1efc5e40e1 | ||
|
|
dc84826d9c | ||
|
|
b4a64ebc44 | ||
|
|
dbb3ccc274 | ||
|
|
9a6ed65cb1 | ||
|
|
21ea67b29c | ||
|
|
ab4be2366f |
@@ -45,7 +45,7 @@ body {
|
||||
|
||||
.jitsi-icon {
|
||||
&-default svg {
|
||||
fill: white;
|
||||
fill: var(--icon-default-color, white);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.always-on-top-toolbox {
|
||||
background-color: $newToolbarBackgroundColor;
|
||||
background-color: var(--toolbox-background-color, $newToolbarBackgroundColor);
|
||||
border-radius: 3px;
|
||||
display: flex;
|
||||
z-index: $toolbarZ;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Round badge.
|
||||
*/
|
||||
.badge-round {
|
||||
background-color: #165ECC;
|
||||
background-color: var(--toolbar-badge-background, #165ECC);
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
color: #FFFFFF;
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
.toolbox-content-wrapper::after {
|
||||
content: '';
|
||||
background: $newToolbarBackgroundColor;
|
||||
background: var(--toolbox-background-color, $newToolbarBackgroundColor);
|
||||
padding-bottom: env(safe-area-inset-bottom, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
}
|
||||
|
||||
#notification-participant-list {
|
||||
background-color: $newToolbarBackgroundColor;
|
||||
background-color: var(--toolbox-background-color, $newToolbarBackgroundColor);
|
||||
border: 1px solid rgba(255, 255, 255, .4);
|
||||
border-radius: 8px;
|
||||
left: 0;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -227,6 +227,9 @@
|
||||
"video_ssrc": "Video SSRC:",
|
||||
"yes": "yes"
|
||||
},
|
||||
"customPanel": {
|
||||
"close": "Close"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "Earlier",
|
||||
"today": "Today",
|
||||
@@ -1315,6 +1318,7 @@
|
||||
"chat": "Open / Close chat",
|
||||
"clap": "Clap",
|
||||
"closeChat": "Close chat",
|
||||
"closeCustomPanel": "Close",
|
||||
"closeMoreActions": "Close more actions menu",
|
||||
"closeParticipantsPane": "Close participants pane",
|
||||
"closedCaptions": "Closed captions",
|
||||
@@ -1420,9 +1424,11 @@
|
||||
"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,13 +240,27 @@ function initCommands() {
|
||||
APP.store.dispatch(muteAllParticipants(exclude, muteMediaType));
|
||||
},
|
||||
'mute-remote-participant': (participantId, mediaType) => {
|
||||
if (!isLocalParticipantModerator(APP.store.getState())) {
|
||||
logger.error('Missing moderator rights to mute remote participant');
|
||||
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;
|
||||
}
|
||||
|
||||
const muteMediaType = mediaType ? mediaType : MEDIA_TYPE.AUDIO;
|
||||
if (!isLocalParticipantModerator(state)) {
|
||||
logger.error('Missing moderator rights to mute remote participant');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
APP.store.dispatch(muteRemote(participantId, muteMediaType));
|
||||
},
|
||||
@@ -1417,17 +1431,15 @@ 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', 'video', or 'desktop').
|
||||
* @param {boolean} isSelfMuted - True if participant muted themselves, false if muted by moderator.
|
||||
* @param {string} mediaType - Media type that was muted ('audio' or 'video').
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyParticipantMuted(participantId, isMuted, mediaType, isSelfMuted = true) {
|
||||
notifyParticipantMuted(participantId, isMuted, mediaType) {
|
||||
this._sendEvent({
|
||||
name: 'participant-muted',
|
||||
id: participantId,
|
||||
isMuted,
|
||||
mediaType,
|
||||
isSelfMuted
|
||||
mediaType
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
2109
package-lock.json
generated
2109
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@@ -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.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",
|
||||
"@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",
|
||||
"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.95.0",
|
||||
"webpack": "5.105.0",
|
||||
"webpack-bundle-analyzer": "4.4.2",
|
||||
"webpack-cli": "5.1.4",
|
||||
"webpack-dev-server": "5.1.0"
|
||||
|
||||
@@ -26,5 +26,6 @@ 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,5 +1,6 @@
|
||||
import '../base/devices/reducer';
|
||||
import '../base/premeeting/reducer';
|
||||
import '../custom-panel/reducer';
|
||||
import '../base/tooltip/reducer';
|
||||
import '../e2ee/reducer';
|
||||
import '../face-landmarks/reducer';
|
||||
|
||||
@@ -31,6 +31,7 @@ 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';
|
||||
@@ -121,6 +122,7 @@ 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;
|
||||
|
||||
@@ -387,7 +387,8 @@ export function setConfigFromURLParams(
|
||||
|
||||
// When not in an iframe, start without media if the pre-join page is not enabled.
|
||||
if (!isEmbedded()
|
||||
&& 'config.prejoinConfig.enabled' in params && config.prejoinConfig?.enabled === false) {
|
||||
&& ('config.prejoinConfig' in params || 'config.prejoinConfig.enabled' in params)
|
||||
&& config.prejoinConfig?.enabled === false) {
|
||||
logger.warn('Using prejoinConfig.enabled config URL overwrite implies starting without media.');
|
||||
config.disableInitialGUM = true;
|
||||
}
|
||||
|
||||
@@ -29,4 +29,3 @@ export function isIpadMobileBrowser() {
|
||||
// @ts-ignore
|
||||
return isIosMobileBrowser() && Platform.isPad;
|
||||
}
|
||||
|
||||
1
react/features/base/environment/utils.native.ts
Normal file
1
react/features/base/environment/utils.native.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './utils.any';
|
||||
37
react/features/base/environment/utils.web.ts
Normal file
37
react/features/base/environment/utils.web.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
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
react/features/base/icons/svg/AI.svg
Normal file
1
react/features/base/icons/svg/AI.svg
Normal file
@@ -0,0 +1 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 582 B |
@@ -1,3 +1,4 @@
|
||||
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';
|
||||
@@ -112,6 +113,7 @@ import { default as IconYahoo } from './yahoo.svg';
|
||||
*/
|
||||
export const DEFAULT_ICON: Record<string, any> = {
|
||||
IconAddUser,
|
||||
IconAI,
|
||||
IconArrowBack,
|
||||
IconArrowDown,
|
||||
IconArrowDownLarge,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { DEFAULT_ICON } from './constants';
|
||||
|
||||
const {
|
||||
IconAddUser,
|
||||
IconAI,
|
||||
IconArrowBack,
|
||||
IconArrowDown,
|
||||
IconArrowDownLarge,
|
||||
@@ -123,6 +124,7 @@ const {
|
||||
|
||||
export {
|
||||
IconAddUser,
|
||||
IconAI,
|
||||
IconArrowBack,
|
||||
IconArrowDown,
|
||||
IconArrowDownLarge,
|
||||
|
||||
@@ -56,9 +56,9 @@ const useStyles = makeStyles()(theme => {
|
||||
label: {
|
||||
...theme.typography.labelRegular,
|
||||
alignItems: 'center',
|
||||
background: theme.palette.ui04,
|
||||
background: theme.palette.labelBackground,
|
||||
borderRadius: '4px',
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.labelText,
|
||||
display: 'flex',
|
||||
margin: '0 2px',
|
||||
padding: '6px',
|
||||
@@ -72,11 +72,11 @@ const useStyles = makeStyles()(theme => {
|
||||
cursor: 'pointer'
|
||||
},
|
||||
[COLORS.white]: {
|
||||
background: theme.palette.ui09,
|
||||
color: theme.palette.text04,
|
||||
background: theme.palette.labelWhiteBackground,
|
||||
color: theme.palette.labelWhiteText,
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.icon04
|
||||
fill: theme.palette.labelWhiteIcon
|
||||
}
|
||||
},
|
||||
[COLORS.green]: {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { IReduxState, IStore } from '../../app/types';
|
||||
import { getLocalParticipant } from '../participants/functions';
|
||||
import StateListenerRegistry from '../redux/StateListenerRegistry';
|
||||
|
||||
/**
|
||||
@@ -13,6 +14,13 @@ 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');
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -84,7 +84,7 @@ const useStyles = makeStyles()(theme => {
|
||||
...theme.typography.bodyLongBold,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
boxSizing: 'border-box',
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.actionButtonText,
|
||||
cursor: 'pointer',
|
||||
display: 'inline-block',
|
||||
marginBottom: '16px',
|
||||
@@ -95,20 +95,20 @@ const useStyles = makeStyles()(theme => {
|
||||
border: 0,
|
||||
|
||||
'&.primary': {
|
||||
background: theme.palette.action01,
|
||||
color: theme.palette.text01,
|
||||
background: theme.palette.prejoinActionButtonPrimary,
|
||||
color: theme.palette.prejoinActionButtonPrimaryText,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.action01Hover
|
||||
backgroundColor: theme.palette.prejoinActionButtonPrimaryHover
|
||||
}
|
||||
},
|
||||
|
||||
'&.secondary': {
|
||||
background: theme.palette.action02,
|
||||
color: theme.palette.text04,
|
||||
background: theme.palette.prejoinActionButtonSecondary,
|
||||
color: theme.palette.prejoinActionButtonSecondaryText,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.action02Hover
|
||||
backgroundColor: theme.palette.prejoinActionButtonSecondaryHover
|
||||
}
|
||||
},
|
||||
|
||||
@@ -120,7 +120,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&.disabled': {
|
||||
background: theme.palette.disabled01,
|
||||
background: theme.palette.prejoinActionButtonDisabled,
|
||||
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.ui01,
|
||||
backgroundColor: theme.palette.preMeetingBackground,
|
||||
zIndex: 252,
|
||||
|
||||
'@media (max-width: 720px)': {
|
||||
@@ -163,7 +163,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
title: {
|
||||
...theme.typography.heading4,
|
||||
color: `${theme.palette.text01}!important`,
|
||||
color: theme.palette.prejoinTitleText,
|
||||
marginBottom: theme.spacing(3),
|
||||
textAlign: 'center',
|
||||
|
||||
@@ -179,7 +179,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
roomName: {
|
||||
...theme.typography.heading5,
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.prejoinRoomNameText,
|
||||
display: 'inline-block',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
|
||||
@@ -6,7 +6,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
warning: {
|
||||
bottom: 0,
|
||||
color: theme.palette.text03,
|
||||
color: theme.palette.prejoinRecordingWarningText,
|
||||
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.warning01,
|
||||
color: theme.palette.text04,
|
||||
backgroundColor: theme.palette.prejoinWarningBackground,
|
||||
color: theme.palette.prejoinWarningText,
|
||||
...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.ui01,
|
||||
border: `1px solid ${theme.palette.ui04}`,
|
||||
backgroundColor: theme.palette.dialogBackground,
|
||||
border: `1px solid ${theme.palette.inlineDialogBorder}`,
|
||||
borderRadius: `${Number(theme.shape.borderRadius)}px`,
|
||||
boxShadow: '0px 1px 2px rgba(41, 41, 41, 0.25)',
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.dialogText,
|
||||
...theme.typography.bodyShortRegular,
|
||||
padding: `${theme.spacing(3)} 10`,
|
||||
'& .retry-button': {
|
||||
|
||||
@@ -2,6 +2,7 @@ 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 {
|
||||
@@ -51,6 +52,7 @@ export function clientResized(clientWidth: number, clientHeight: number) {
|
||||
}
|
||||
|
||||
availableWidth -= getParticipantsPaneWidth(state);
|
||||
availableWidth -= getCustomPanelWidth(state);
|
||||
|
||||
reducedUIEnabled && dispatch(setReducedUI(availableWidth, clientHeight));
|
||||
}
|
||||
|
||||
@@ -22,11 +22,11 @@ interface IProps {
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
container: {
|
||||
backgroundColor: theme.palette.uiBackground,
|
||||
backgroundColor: theme.palette.tooltipBackground,
|
||||
borderRadius: '3px',
|
||||
padding: theme.spacing(2),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.tooltipText,
|
||||
position: 'relative',
|
||||
|
||||
'&.mounting-animation': {
|
||||
|
||||
@@ -51,7 +51,7 @@ import './subscriber.web';
|
||||
MiddlewareRegistry.register(store => next => action => {
|
||||
switch (action.type) {
|
||||
case TRACK_ADDED: {
|
||||
const { local } = action.track;
|
||||
const { local, jitsiTrack } = 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,6 +65,16 @@ 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;
|
||||
@@ -119,6 +129,16 @@ 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();
|
||||
|
||||
@@ -126,11 +146,6 @@ 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();
|
||||
@@ -144,12 +159,14 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
if (typeof action.track?.muted !== 'undefined' && participantID && !local) {
|
||||
logTracksForParticipant(store.getState()['features/base/tracks'], participantID, 'Track updated');
|
||||
|
||||
// Notify external API when remote participant mutes/unmutes themselves
|
||||
const mediaType = isVideoTrack
|
||||
? (jitsiTrack.getVideoType() === VIDEO_TYPE.DESKTOP ? 'desktop' : 'video')
|
||||
: 'audio';
|
||||
// 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';
|
||||
|
||||
APP.API.notifyParticipantMuted(participantID, action.track.muted, mediaType, true);
|
||||
APP.API.notifyParticipantMuted(participantID, action.track.muted, mediaType);
|
||||
}
|
||||
}
|
||||
|
||||
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 { getScreenshareParticipantIds } from '../participants/functions';
|
||||
import { getLocalParticipant, getScreenshareParticipantIds } from '../participants/functions';
|
||||
import StateListenerRegistry from '../redux/StateListenerRegistry';
|
||||
|
||||
import { isLocalTrackMuted } from './functions';
|
||||
@@ -47,6 +47,13 @@ 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,3 +1,4 @@
|
||||
/* eslint-disable @stylistic/no-multi-spaces */
|
||||
// Mapping between the token used and the color
|
||||
export const colorMap = {
|
||||
// ----- Surfaces -----
|
||||
@@ -7,7 +8,7 @@ export const colorMap = {
|
||||
// - JitsiMeetView.java
|
||||
uiBackground: 'surface01',
|
||||
|
||||
// Container backgrounds
|
||||
// Container backgrounds (legacy tokens)
|
||||
ui01: 'surface02',
|
||||
ui02: 'surface03',
|
||||
ui03: 'ui02',
|
||||
@@ -47,6 +48,426 @@ 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.text01,
|
||||
color: theme.palette.dialogText,
|
||||
...theme.typography.bodyLongRegular,
|
||||
top: 0,
|
||||
left: 0,
|
||||
@@ -49,13 +49,13 @@ const useStyles = makeStyles()(theme => {
|
||||
height: '100%',
|
||||
top: 0,
|
||||
left: 0,
|
||||
backgroundColor: theme.palette.ui02,
|
||||
backgroundColor: theme.palette.dialogOverlay,
|
||||
opacity: 0.75
|
||||
},
|
||||
|
||||
modal: {
|
||||
backgroundColor: theme.palette.ui01,
|
||||
border: `1px solid ${theme.palette.ui03}`,
|
||||
backgroundColor: theme.palette.dialogBackground,
|
||||
border: `1px solid ${theme.palette.dialogBorder}`,
|
||||
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.text01,
|
||||
color: theme.palette.checkboxLabel,
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
|
||||
@@ -76,10 +76,10 @@ const useStyles = makeStyles()(theme => {
|
||||
backgroundColor: 'transparent',
|
||||
margin: '3px',
|
||||
font: 'inherit',
|
||||
color: theme.palette.icon03,
|
||||
color: theme.palette.checkboxBorder,
|
||||
width: '18px',
|
||||
height: '18px',
|
||||
border: `2px solid ${theme.palette.icon03}`,
|
||||
border: `2px solid ${theme.palette.checkboxBorder}`,
|
||||
borderRadius: '3px',
|
||||
|
||||
display: 'grid',
|
||||
@@ -90,7 +90,7 @@ const useStyles = makeStyles()(theme => {
|
||||
width: '18px',
|
||||
height: '18px',
|
||||
opacity: 0,
|
||||
backgroundColor: theme.palette.action01,
|
||||
backgroundColor: theme.palette.checkboxChecked,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
@@ -104,11 +104,11 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
backgroundColor: theme.palette.ui03,
|
||||
borderColor: theme.palette.ui04,
|
||||
backgroundColor: theme.palette.checkboxDisabledBackground,
|
||||
borderColor: theme.palette.checkboxDisabledBorder,
|
||||
|
||||
'&::before': {
|
||||
backgroundColor: theme.palette.ui04
|
||||
backgroundColor: theme.palette.checkboxDisabledChecked
|
||||
}
|
||||
},
|
||||
|
||||
@@ -173,7 +173,7 @@ const Checkbox = ({
|
||||
<Icon
|
||||
aria-hidden = { true }
|
||||
className = 'checkmark'
|
||||
color = { disabled ? theme.palette.icon03 : theme.palette.icon01 }
|
||||
color = { disabled ? theme.palette.checkboxIconDisabled : theme.palette.checkboxIcon }
|
||||
size = { 18 }
|
||||
src = { IconCheck } />
|
||||
</div>
|
||||
|
||||
@@ -16,22 +16,22 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
button: {
|
||||
padding: '2px',
|
||||
backgroundColor: theme.palette.action03,
|
||||
backgroundColor: theme.palette.clickableIconBackground,
|
||||
border: 0,
|
||||
outline: 0,
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.ui02
|
||||
backgroundColor: theme.palette.clickableIconHover
|
||||
},
|
||||
|
||||
'&.focus-visible': {
|
||||
outline: 0,
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.clickableIconFocus}`
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.palette.ui03
|
||||
backgroundColor: theme.palette.clickableIconActive
|
||||
},
|
||||
|
||||
'&.is-mobile': {
|
||||
|
||||
@@ -133,11 +133,11 @@ const MAX_HEIGHT = 400;
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
contextMenu: {
|
||||
backgroundColor: theme.palette.ui01,
|
||||
border: `1px solid ${theme.palette.ui04}`,
|
||||
backgroundColor: theme.palette.overflowMenuBackground,
|
||||
border: `1px solid ${theme.palette.overflowMenuBorder}`,
|
||||
borderRadius: `${Number(theme.shape.borderRadius)}px`,
|
||||
boxShadow: '0px 1px 2px rgba(41, 41, 41, 0.25)',
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.overflowMenuItemText,
|
||||
...theme.typography.bodyShortRegular,
|
||||
marginTop: '48px',
|
||||
position: 'absolute',
|
||||
|
||||
@@ -122,11 +122,11 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.ui02
|
||||
backgroundColor: theme.palette.overflowMenuItemHover
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.palette.ui03
|
||||
backgroundColor: theme.palette.overflowMenuItemHover
|
||||
},
|
||||
|
||||
'&.focus-visible': {
|
||||
@@ -137,7 +137,7 @@ const useStyles = makeStyles()(theme => {
|
||||
selected: {
|
||||
borderLeft: `3px solid ${theme.palette.action01Hover}`,
|
||||
paddingLeft: '13px',
|
||||
backgroundColor: theme.palette.ui02
|
||||
backgroundColor: theme.palette.overflowMenuItemHover
|
||||
},
|
||||
|
||||
contextMenuItemDisabled: {
|
||||
@@ -146,19 +146,19 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
contextMenuItemIconDisabled: {
|
||||
'& svg': {
|
||||
fill: `${theme.palette.text03} !important`
|
||||
fill: `${theme.palette.overflowMenuItemDisabled} !important`
|
||||
}
|
||||
},
|
||||
|
||||
contextMenuItemLabelDisabled: {
|
||||
color: theme.palette.text03,
|
||||
color: theme.palette.overflowMenuItemDisabled,
|
||||
|
||||
'&:hover': {
|
||||
background: 'none'
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.text03
|
||||
fill: theme.palette.overflowMenuItemDisabled
|
||||
}
|
||||
},
|
||||
|
||||
@@ -168,13 +168,13 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
contextMenuItemIcon: {
|
||||
'& svg': {
|
||||
fill: theme.palette.icon01
|
||||
fill: theme.palette.overflowMenuItemIcon
|
||||
}
|
||||
},
|
||||
|
||||
text: {
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text01
|
||||
color: theme.palette.overflowMenuItemText
|
||||
},
|
||||
|
||||
drawerText: {
|
||||
|
||||
@@ -30,7 +30,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'& + &:not(:empty)': {
|
||||
borderTop: `1px solid ${theme.palette.ui03}`
|
||||
borderTop: `1px solid ${theme.palette.overflowMenuSeparator}`
|
||||
},
|
||||
|
||||
'&:first-of-type': {
|
||||
|
||||
@@ -24,7 +24,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
title: {
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.dialogText,
|
||||
...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.ui03}`,
|
||||
borderRight: `1px solid ${theme.palette.dialogBorder}`,
|
||||
|
||||
[`@media (max-width: ${MOBILE_BREAKPOINT}px)`]: {
|
||||
width: '100%',
|
||||
@@ -70,7 +70,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
title: {
|
||||
...theme.typography.heading5,
|
||||
color: `${theme.palette.text01} !important`,
|
||||
color: `${theme.palette.dialogText} !important`,
|
||||
margin: 0,
|
||||
padding: 0
|
||||
},
|
||||
@@ -301,7 +301,7 @@ const DialogWithTabs = ({
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [ selectedTabIndex, tabStates ]);
|
||||
}, [ selectedTabIndex, tabStates, tabs ]);
|
||||
|
||||
const closeIcon = useMemo(() => (
|
||||
<ClickableIcon
|
||||
|
||||
@@ -49,7 +49,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
label: {
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.inputLabel,
|
||||
...theme.typography.bodyShortRegular,
|
||||
marginBottom: theme.spacing(2),
|
||||
|
||||
@@ -64,9 +64,9 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
input: {
|
||||
backgroundColor: theme.palette.ui03,
|
||||
background: theme.palette.ui03,
|
||||
color: theme.palette.text01,
|
||||
backgroundColor: theme.palette.inputFieldBackground,
|
||||
background: theme.palette.inputFieldBackground,
|
||||
color: theme.palette.inputFieldText,
|
||||
...theme.typography.bodyShortRegular,
|
||||
padding: '10px 16px',
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
@@ -76,16 +76,16 @@ const useStyles = makeStyles()(theme => {
|
||||
width: '100%',
|
||||
|
||||
'&::placeholder': {
|
||||
color: theme.palette.text02
|
||||
color: theme.palette.inputFieldPlaceholder
|
||||
},
|
||||
|
||||
'&:focus': {
|
||||
outline: 0,
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.inputFieldFocus}`
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
color: theme.palette.text03
|
||||
color: theme.palette.inputFieldDisabled
|
||||
},
|
||||
|
||||
'&.is-mobile': {
|
||||
@@ -99,7 +99,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&.error': {
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.textError}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.inputFieldError}`
|
||||
},
|
||||
'&.clearable-input': {
|
||||
paddingRight: '46px'
|
||||
@@ -131,7 +131,7 @@ const useStyles = makeStyles()(theme => {
|
||||
right: '16px',
|
||||
top: '10px',
|
||||
cursor: 'pointer',
|
||||
backgroundColor: theme.palette.action03,
|
||||
backgroundColor: theme.palette.inputClearButton,
|
||||
border: 0,
|
||||
padding: 0
|
||||
},
|
||||
@@ -139,14 +139,14 @@ const useStyles = makeStyles()(theme => {
|
||||
bottomLabel: {
|
||||
marginTop: theme.spacing(2),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.inputBottomLabel,
|
||||
|
||||
'&.is-mobile': {
|
||||
...theme.typography.bodyShortRegular
|
||||
},
|
||||
|
||||
'&.error': {
|
||||
color: theme.palette.textError
|
||||
color: theme.palette.inputBottomLabelError
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -83,7 +83,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.listItemText,
|
||||
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.ui02,
|
||||
backgroundColor: theme.palette.listItemHover,
|
||||
|
||||
'& .indicators': {
|
||||
display: 'none'
|
||||
@@ -103,8 +103,8 @@ const useStyles = makeStyles()(theme => {
|
||||
display: 'flex',
|
||||
position: 'relative',
|
||||
top: 'auto',
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.ui02}`,
|
||||
backgroundColor: theme.palette.ui02
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.listItemBoxShadow}`,
|
||||
backgroundColor: theme.palette.listItemHover
|
||||
}
|
||||
},
|
||||
|
||||
@@ -115,14 +115,14 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
highlighted: {
|
||||
backgroundColor: theme.palette.ui02,
|
||||
backgroundColor: theme.palette.listItemHighlighted,
|
||||
|
||||
'& .actions': {
|
||||
display: 'flex',
|
||||
position: 'relative',
|
||||
top: 'auto',
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.ui02}`,
|
||||
backgroundColor: theme.palette.ui02
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.listItemBoxShadow}`,
|
||||
backgroundColor: theme.palette.listItemHighlighted
|
||||
}
|
||||
},
|
||||
|
||||
@@ -170,20 +170,20 @@ const useStyles = makeStyles()(theme => {
|
||||
actionsContainer: {
|
||||
position: 'absolute',
|
||||
top: '-1000px',
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.ui02}`,
|
||||
backgroundColor: theme.palette.ui02
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.listItemBoxShadow}`,
|
||||
backgroundColor: theme.palette.listItemHover
|
||||
},
|
||||
|
||||
actionsPermanent: {
|
||||
display: 'flex',
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.ui01}`,
|
||||
backgroundColor: theme.palette.ui01
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.listItemBackground}`,
|
||||
backgroundColor: theme.palette.listItemBackground
|
||||
},
|
||||
|
||||
actionsVisible: {
|
||||
display: 'flex',
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.ui02}`,
|
||||
backgroundColor: theme.palette.ui02
|
||||
boxShadow: `-15px 0px 10px -5px ${theme.palette.listItemBoxShadow}`,
|
||||
backgroundColor: theme.palette.listItemHighlighted
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -38,8 +38,8 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
marginTop: theme.spacing(2),
|
||||
width: '100%',
|
||||
backgroundColor: theme.palette.ui01,
|
||||
border: `1px solid ${theme.palette.ui04}`,
|
||||
backgroundColor: theme.palette.multiSelectBackground,
|
||||
border: `1px solid ${theme.palette.multiSelectBorder}`,
|
||||
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.text01,
|
||||
color: theme.palette.multiSelectItemText,
|
||||
'&.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.ui02
|
||||
backgroundColor: theme.palette.multiSelectItemHover
|
||||
}
|
||||
},
|
||||
'&.disabled': {
|
||||
cursor: 'not-allowed',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.ui01
|
||||
backgroundColor: theme.palette.multiSelectBackground
|
||||
},
|
||||
color: theme.palette.text03
|
||||
color: theme.palette.multiSelectItemDisabled
|
||||
}
|
||||
},
|
||||
errorMessage: {
|
||||
|
||||
@@ -70,7 +70,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
label: {
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.selectLabel,
|
||||
...theme.typography.bodyShortRegular,
|
||||
marginBottom: theme.spacing(2),
|
||||
|
||||
@@ -84,11 +84,11 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
select: {
|
||||
backgroundColor: theme.palette.ui03,
|
||||
backgroundColor: theme.palette.selectBackground,
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
width: '100%',
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.selectText,
|
||||
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.focus01}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.selectFocus}`
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
color: theme.palette.text03
|
||||
color: theme.palette.selectDisabled
|
||||
},
|
||||
|
||||
'&.is-mobile': {
|
||||
@@ -113,7 +113,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&.error': {
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.textError}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.selectError}`
|
||||
}
|
||||
},
|
||||
|
||||
@@ -132,14 +132,14 @@ const useStyles = makeStyles()(theme => {
|
||||
bottomLabel: {
|
||||
marginTop: theme.spacing(2),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.selectBottomLabel,
|
||||
|
||||
'&.is-mobile': {
|
||||
...theme.typography.bodyShortRegular
|
||||
},
|
||||
|
||||
'&.error': {
|
||||
color: theme.palette.textError
|
||||
color: theme.palette.selectBottomLabelError
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -180,7 +180,7 @@ const Select = ({
|
||||
</select>
|
||||
<Icon
|
||||
className = { cx(classes.icon, isMobile && 'is-mobile') }
|
||||
color = { disabled ? theme.palette.icon03 : theme.palette.icon01 }
|
||||
color = { disabled ? theme.palette.selectIconDisabled : theme.palette.selectIcon }
|
||||
size = { 22 }
|
||||
src = { IconArrowDown } />
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
container: {
|
||||
position: 'relative',
|
||||
backgroundColor: theme.palette.ui05,
|
||||
backgroundColor: theme.palette.switchBackground,
|
||||
borderRadius: '12px',
|
||||
width: '40px',
|
||||
height: '24px',
|
||||
@@ -29,11 +29,11 @@ const useStyles = makeStyles()(theme => {
|
||||
display: 'inline-block',
|
||||
|
||||
'&.disabled': {
|
||||
backgroundColor: theme.palette.ui05,
|
||||
backgroundColor: theme.palette.switchBackground,
|
||||
cursor: 'default',
|
||||
|
||||
'& .toggle': {
|
||||
backgroundColor: theme.palette.ui03
|
||||
backgroundColor: theme.palette.switchToggleDisabled
|
||||
}
|
||||
},
|
||||
|
||||
@@ -45,7 +45,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
containerOn: {
|
||||
backgroundColor: theme.palette.action01
|
||||
backgroundColor: theme.palette.switchBackgroundOn
|
||||
},
|
||||
|
||||
toggle: {
|
||||
@@ -55,7 +55,7 @@ const useStyles = makeStyles()(theme => {
|
||||
zIndex: 5,
|
||||
top: '4px',
|
||||
left: '4px',
|
||||
backgroundColor: theme.palette.ui10,
|
||||
backgroundColor: theme.palette.switchToggle,
|
||||
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.focus01}`
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.switchFocus}`
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -29,13 +29,13 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
tab: {
|
||||
...theme.typography.bodyShortBold,
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.tabText,
|
||||
flex: 1,
|
||||
padding: '14px',
|
||||
background: 'none',
|
||||
border: 0,
|
||||
appearance: 'none',
|
||||
borderBottom: `2px solid ${theme.palette.ui05}`,
|
||||
borderBottom: `2px solid ${theme.palette.tabBorder}`,
|
||||
transition: 'color, border-color 0.2s',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
@@ -43,25 +43,25 @@ const useStyles = makeStyles()(theme => {
|
||||
borderRadius: 0,
|
||||
|
||||
'&:hover': {
|
||||
color: theme.palette.text01,
|
||||
borderColor: theme.palette.ui10
|
||||
color: theme.palette.tabTextHover,
|
||||
borderColor: theme.palette.tabBorderHover
|
||||
},
|
||||
|
||||
'&.focus-visible': {
|
||||
outline: 0,
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`,
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.tabFocus}`,
|
||||
border: 0,
|
||||
color: theme.palette.text01
|
||||
color: theme.palette.tabTextSelected
|
||||
},
|
||||
|
||||
'&.selected': {
|
||||
color: theme.palette.text01,
|
||||
borderColor: theme.palette.action01
|
||||
color: theme.palette.tabTextSelected,
|
||||
borderColor: theme.palette.tabBorderSelected
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
color: theme.palette.text03,
|
||||
borderColor: theme.palette.ui05
|
||||
color: theme.palette.tabTextDisabled,
|
||||
borderColor: theme.palette.tabBorderDisabled
|
||||
},
|
||||
|
||||
'&.is-mobile': {
|
||||
@@ -72,9 +72,9 @@ const useStyles = makeStyles()(theme => {
|
||||
badge: {
|
||||
...theme.typography.labelBold,
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.warning01,
|
||||
backgroundColor: theme.palette.tabBadgeBackground,
|
||||
borderRadius: theme.spacing(2),
|
||||
color: theme.palette.text04,
|
||||
color: theme.palette.tabBadgeText,
|
||||
display: 'inline-flex',
|
||||
height: theme.spacing(3),
|
||||
justifyContent: 'center',
|
||||
|
||||
@@ -11,6 +11,23 @@ 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,
|
||||
@@ -39,7 +56,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
|
||||
'.overflow-menu-item': {
|
||||
alignItems: 'center',
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.overflowMenuItemText,
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
fontSize: '0.875rem',
|
||||
@@ -59,20 +76,20 @@ export const commonStyles = (theme: Theme) => {
|
||||
|
||||
'&.disabled': {
|
||||
cursor: 'initial',
|
||||
color: theme.palette.text03,
|
||||
color: theme.palette.overflowMenuItemDisabled,
|
||||
|
||||
'&:hover': {
|
||||
background: 'none'
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.text03
|
||||
fill: theme.palette.overflowMenuItemDisabled
|
||||
}
|
||||
},
|
||||
|
||||
'@media (hover: hover) and (pointer: fine)': {
|
||||
'&:hover': {
|
||||
background: theme.palette.action02Hover
|
||||
background: theme.palette.overflowMenuItemHover
|
||||
},
|
||||
'&.unclickable:hover': {
|
||||
background: 'inherit'
|
||||
@@ -100,14 +117,14 @@ export const commonStyles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.text01,
|
||||
fill: theme.palette.overflowMenuItemIcon,
|
||||
height: 20,
|
||||
width: 20
|
||||
}
|
||||
},
|
||||
|
||||
'.prejoin-dialog': {
|
||||
backgroundColor: theme.palette.uiBackground,
|
||||
backgroundColor: theme.palette.prejoinDialogBackground,
|
||||
boxShadow: '0px 2px 20px rgba(0, 0, 0, 0.5)',
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
color: '#fff',
|
||||
@@ -173,7 +190,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'.prejoin-dialog-delimiter': {
|
||||
background: theme.palette.ui03,
|
||||
background: theme.palette.prejoinDialogDelimiter,
|
||||
border: '0',
|
||||
height: '1px',
|
||||
margin: '0',
|
||||
@@ -194,8 +211,8 @@ export const commonStyles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'.prejoin-dialog-delimiter-txt': {
|
||||
background: theme.palette.uiBackground,
|
||||
color: theme.palette.text01,
|
||||
background: theme.palette.prejoinDialogBackground,
|
||||
color: theme.palette.prejoinDialogDelimiterText,
|
||||
fontSize: '0.75rem',
|
||||
textTransform: 'uppercase' as const,
|
||||
padding: `0 ${theme.spacing(2)}`
|
||||
@@ -219,11 +236,11 @@ export const commonStyles = (theme: Theme) => {
|
||||
|
||||
'@media (hover: hover) and (pointer: fine)': {
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.ui04
|
||||
backgroundColor: theme.palette.toolboxIconHover
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.palette.ui03
|
||||
backgroundColor: theme.palette.toolboxIconActive
|
||||
}
|
||||
},
|
||||
[theme.breakpoints.down(320)]: {
|
||||
@@ -232,7 +249,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'&.toggled': {
|
||||
backgroundColor: theme.palette.ui03
|
||||
backgroundColor: theme.palette.toolboxIconToggled
|
||||
},
|
||||
|
||||
'&.disabled': {
|
||||
@@ -240,13 +257,13 @@ export const commonStyles = (theme: Theme) => {
|
||||
backgroundColor: `${theme.palette.disabled01} !important`,
|
||||
|
||||
'& svg': {
|
||||
fill: `${theme.palette.text03} !important`
|
||||
fill: `${theme.palette.icon03} !important`
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'.toolbox-button': {
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.toolbarIcon,
|
||||
cursor: 'pointer',
|
||||
display: 'inline-block',
|
||||
lineHeight: '3rem',
|
||||
@@ -254,7 +271,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'.toolbox-content-items': {
|
||||
background: theme.palette.ui01,
|
||||
background: theme.palette.toolboxBackground,
|
||||
borderRadius: 6,
|
||||
margin: '0 auto',
|
||||
padding: 6,
|
||||
|
||||
11
react/features/base/ui/types.d.ts
vendored
Normal file
11
react/features/base/ui/types.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
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,6 +5,7 @@ interface ITypographyType {
|
||||
lineHeight: string;
|
||||
}
|
||||
|
||||
/* eslint-disable typescript-sort-keys/interface */
|
||||
export interface IPalette {
|
||||
action01: string;
|
||||
action01Active: string;
|
||||
@@ -58,6 +59,324 @@ 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,13 +11,49 @@ import * as tokens from './tokens.json';
|
||||
*/
|
||||
export function createColorTokens(colorMap: Object): any {
|
||||
const allTokens = merge({}, tokens, jitsiTokens);
|
||||
const result: any = {};
|
||||
|
||||
return Object.entries(colorMap)
|
||||
.reduce((result, [ token, value ]: [any, string]) => {
|
||||
const color = allTokens[value as keyof typeof allTokens] || value;
|
||||
// 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.assign(result, { [token]: color });
|
||||
}, {});
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,7 @@ 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';
|
||||
@@ -23,7 +24,16 @@ import {
|
||||
setUserChatWidth,
|
||||
toggleChat
|
||||
} from '../../actions.web';
|
||||
import { CHAT_SIZE, ChatTabs, OPTION_GROUPCHAT, SMALL_WIDTH_THRESHOLD } from '../../constants';
|
||||
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 { getChatMaxSize, getFocusedTab, isChatDisabled } from '../../functions';
|
||||
import { IChatProps as AbstractProps } from '../../types';
|
||||
|
||||
@@ -104,10 +114,15 @@ interface IProps extends AbstractProps {
|
||||
_width: number;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles<{ _isResizing: boolean; width: number; }>()((theme, { _isResizing, width }) => {
|
||||
const useStyles = makeStyles<{
|
||||
_isResizing: boolean;
|
||||
isTouch: boolean;
|
||||
resizeEnabled: boolean;
|
||||
width: number;
|
||||
}>()((theme, { _isResizing, isTouch, resizeEnabled, width }) => {
|
||||
return {
|
||||
container: {
|
||||
backgroundColor: theme.palette.ui01,
|
||||
backgroundColor: theme.palette.chatBackground,
|
||||
flexShrink: 0,
|
||||
overflow: 'hidden',
|
||||
position: 'relative',
|
||||
@@ -115,11 +130,15 @@ const useStyles = makeStyles<{ _isResizing: boolean; width: number; }>()((theme,
|
||||
width: `${width}px`,
|
||||
zIndex: 300,
|
||||
|
||||
'&:hover, &:focus-within': {
|
||||
'& .dragHandleContainer': {
|
||||
visibility: 'visible'
|
||||
// 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'
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
'@media (max-width: 580px)': {
|
||||
height: '100dvh',
|
||||
@@ -146,7 +165,7 @@ const useStyles = makeStyles<{ _isResizing: boolean; width: number; }>()((theme,
|
||||
padding: `${theme.spacing(3)} ${theme.spacing(4)}`,
|
||||
alignItems: 'center',
|
||||
boxSizing: 'border-box',
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.chatMessageText,
|
||||
...theme.typography.heading6,
|
||||
lineHeight: 'unset',
|
||||
fontWeight: theme.typography.heading6.fontWeight as any,
|
||||
@@ -183,16 +202,23 @@ const useStyles = makeStyles<{ _isResizing: boolean; width: number; }>()((theme,
|
||||
|
||||
dragHandleContainer: {
|
||||
height: '100%',
|
||||
width: '9px',
|
||||
// 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`,
|
||||
backgroundColor: 'transparent',
|
||||
position: 'absolute',
|
||||
cursor: 'col-resize',
|
||||
display: 'flex',
|
||||
display: resizeEnabled ? 'flex' : 'none', // Hide if resize not enabled
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
visibility: 'hidden',
|
||||
right: '4px',
|
||||
// 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`,
|
||||
top: 0,
|
||||
// Prevent touch scrolling while dragging
|
||||
touchAction: 'none',
|
||||
|
||||
'&:hover': {
|
||||
'& .dragHandle': {
|
||||
@@ -210,10 +236,15 @@ const useStyles = makeStyles<{ _isResizing: boolean; width: number; }>()((theme,
|
||||
},
|
||||
|
||||
dragHandle: {
|
||||
// Keep the same visual appearance on all devices
|
||||
backgroundColor: theme.palette.icon02,
|
||||
height: '100px',
|
||||
width: '3px',
|
||||
borderRadius: '1px'
|
||||
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
|
||||
})
|
||||
},
|
||||
|
||||
privateMessageRecipientsList: {
|
||||
@@ -246,7 +277,10 @@ const Chat = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
const { classes, cx } = useStyles({ _isResizing, width: _width });
|
||||
// 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 [ isMouseDown, setIsMouseDown ] = useState(false);
|
||||
const [ mousePosition, setMousePosition ] = useState<number | null>(null);
|
||||
const [ dragChatWidth, setDragChatWidth ] = useState<number | null>(null);
|
||||
@@ -282,16 +316,21 @@ const Chat = ({
|
||||
}, [ participants, defaultRemoteDisplayName, t, notifyTimestamp ]);
|
||||
|
||||
/**
|
||||
* Handles mouse down on the drag handle.
|
||||
* Handles pointer down on the drag handle.
|
||||
* Supports both mouse and touch events via Pointer Events API.
|
||||
*
|
||||
* @param {MouseEvent} e - The mouse down event.
|
||||
* @param {React.PointerEvent} e - The pointer down event.
|
||||
* @returns {void}
|
||||
*/
|
||||
const onDragHandleMouseDown = useCallback((e: React.MouseEvent) => {
|
||||
const onDragHandlePointerDown = useCallback((e: React.PointerEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Store the initial mouse position and chat width
|
||||
// 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
|
||||
setIsMouseDown(true);
|
||||
setMousePosition(e.clientX);
|
||||
setDragChatWidth(_width);
|
||||
@@ -299,7 +338,7 @@ const Chat = ({
|
||||
// Indicate that resizing is in progress
|
||||
dispatch(setChatIsResizing(true));
|
||||
|
||||
// Add visual feedback that we're dragging
|
||||
// Add visual feedback that we're dragging (cursor for mouse, not visible on touch)
|
||||
document.body.style.cursor = 'col-resize';
|
||||
|
||||
// Disable text selection during resize
|
||||
@@ -307,11 +346,12 @@ const Chat = ({
|
||||
}, [ _width, dispatch ]);
|
||||
|
||||
/**
|
||||
* Drag handle mouse up handler.
|
||||
* Drag handle pointer up handler.
|
||||
* Supports both mouse and touch events via Pointer Events API.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
const onDragMouseUp = useCallback(() => {
|
||||
const onDragPointerUp = useCallback(() => {
|
||||
if (isMouseDown) {
|
||||
setIsMouseDown(false);
|
||||
dispatch(setChatIsResizing(false));
|
||||
@@ -323,12 +363,13 @@ const Chat = ({
|
||||
}, [ isMouseDown, dispatch ]);
|
||||
|
||||
/**
|
||||
* Handles drag handle mouse move.
|
||||
* Handles drag handle pointer move.
|
||||
* Supports both mouse and touch events via Pointer Events API.
|
||||
*
|
||||
* @param {MouseEvent} e - The mousemove event.
|
||||
* @param {PointerEvent} e - The pointermove event.
|
||||
* @returns {void}
|
||||
*/
|
||||
const onChatResize = useCallback(throttle((e: MouseEvent) => {
|
||||
const onChatResize = useCallback(throttle((e: PointerEvent) => {
|
||||
if (isMouseDown && mousePosition !== null && dragChatWidth !== null) {
|
||||
// For chat panel resizing on the left edge:
|
||||
// - Dragging left (decreasing X coordinate) should make the panel wider
|
||||
@@ -352,14 +393,14 @@ const Chat = ({
|
||||
|
||||
// Set up event listeners when component mounts
|
||||
useEffect(() => {
|
||||
document.addEventListener('mouseup', onDragMouseUp);
|
||||
document.addEventListener('mousemove', onChatResize);
|
||||
document.addEventListener('pointerup', onDragPointerUp);
|
||||
document.addEventListener('pointermove', onChatResize);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mouseup', onDragMouseUp);
|
||||
document.removeEventListener('mousemove', onChatResize);
|
||||
document.removeEventListener('pointerup', onDragPointerUp);
|
||||
document.removeEventListener('pointermove', onChatResize);
|
||||
};
|
||||
}, [ onDragMouseUp, onChatResize ]);
|
||||
}, [ onDragPointerUp, onChatResize ]);
|
||||
|
||||
/**
|
||||
* Sends a text message.
|
||||
@@ -600,7 +641,7 @@ const Chat = ({
|
||||
(isMouseDown || _isResizing) && 'visible',
|
||||
'dragHandleContainer'
|
||||
) }
|
||||
onMouseDown = { onDragHandleMouseDown }>
|
||||
onPointerDown = { onDragHandlePointerDown }>
|
||||
<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.ui02}`,
|
||||
borderTop: `1px solid ${_theme.palette.chatInputBorder}`,
|
||||
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.ui02,
|
||||
backgroundColor: theme.palette.chatMessageRemote,
|
||||
borderRadius: '4px 12px 12px 12px',
|
||||
maxWidth: '100%',
|
||||
marginTop: '4px',
|
||||
@@ -66,21 +66,21 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
|
||||
'&.privatemessage': {
|
||||
backgroundColor: theme.palette.support05
|
||||
backgroundColor: theme.palette.chatMessagePrivate
|
||||
},
|
||||
'&.local': {
|
||||
backgroundColor: theme.palette.ui04,
|
||||
backgroundColor: theme.palette.chatMessageLocal,
|
||||
borderRadius: '12px 4px 12px 12px',
|
||||
|
||||
'&.privatemessage': {
|
||||
backgroundColor: theme.palette.support05
|
||||
backgroundColor: theme.palette.chatMessagePrivate
|
||||
},
|
||||
'&.local': {
|
||||
backgroundColor: theme.palette.ui04,
|
||||
backgroundColor: theme.palette.chatMessageLocal,
|
||||
borderRadius: '12px 4px 12px 12px',
|
||||
|
||||
'&.privatemessage': {
|
||||
backgroundColor: theme.palette.support05
|
||||
backgroundColor: theme.palette.chatMessagePrivate
|
||||
}
|
||||
},
|
||||
|
||||
@@ -91,7 +91,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
|
||||
'&.lobbymessage': {
|
||||
backgroundColor: theme.palette.support05
|
||||
backgroundColor: theme.palette.chatMessagePrivate
|
||||
}
|
||||
},
|
||||
'&.error': {
|
||||
@@ -100,7 +100,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
fontWeight: 100
|
||||
},
|
||||
'&.lobbymessage': {
|
||||
backgroundColor: theme.palette.support05
|
||||
backgroundColor: theme.palette.chatMessagePrivate
|
||||
}
|
||||
},
|
||||
sideBySideContainer: {
|
||||
@@ -146,7 +146,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
displayName: {
|
||||
...theme.typography.labelBold,
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.chatSenderName,
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
overflow: 'hidden',
|
||||
@@ -155,18 +155,18 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
userMessage: {
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.chatMessageText,
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-word'
|
||||
},
|
||||
privateMessageNotice: {
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.chatPrivateNotice,
|
||||
marginTop: theme.spacing(1)
|
||||
},
|
||||
timestamp: {
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text03,
|
||||
color: theme.palette.chatTimestamp,
|
||||
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.ui03,
|
||||
backgroundColor: theme.palette.chatInputBackground,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
maxWidth: '150px',
|
||||
maxHeight: '400px',
|
||||
overflowY: 'auto',
|
||||
color: theme.palette.text01
|
||||
color: theme.palette.chatMessageText
|
||||
},
|
||||
reactionItem: {
|
||||
display: 'flex',
|
||||
|
||||
@@ -24,7 +24,7 @@ const useStyles = makeStyles()(theme => {
|
||||
padding: '16px',
|
||||
flex: 1,
|
||||
boxSizing: 'border-box',
|
||||
color: theme.palette.text01
|
||||
color: theme.palette.chatMessageText
|
||||
},
|
||||
container: {
|
||||
display: 'flex',
|
||||
@@ -48,7 +48,7 @@ const useStyles = makeStyles()(theme => {
|
||||
boxSizing: 'border-box',
|
||||
flexDirection: 'column',
|
||||
gap: '16px',
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.chatMessageText,
|
||||
textAlign: 'center'
|
||||
},
|
||||
emptyIcon: {
|
||||
@@ -62,7 +62,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
emptyState: {
|
||||
...theme.typography.bodyLongBold,
|
||||
color: theme.palette.text02
|
||||
color: theme.palette.chatSenderName
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -103,7 +103,7 @@ const ClosedCaptionsTab = ({
|
||||
<div className = { classes.emptyContent }>
|
||||
<Icon
|
||||
className = { classes.emptyIcon }
|
||||
color = { theme.palette.icon03 }
|
||||
color = { theme.palette.chatEmptyText }
|
||||
src = { IconSubtitles } />
|
||||
<span className = { classes.emptyState }>
|
||||
{ t('closedCaptionsTab.emptyState') }
|
||||
|
||||
@@ -12,7 +12,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
borderRadius: '4px',
|
||||
backgroundColor: theme.palette.ui03
|
||||
backgroundColor: theme.palette.chatInputBackground
|
||||
},
|
||||
|
||||
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.ui02,
|
||||
backgroundColor: theme.palette.chatMessageRemote,
|
||||
paddingLeft: theme.spacing(2)
|
||||
},
|
||||
|
||||
'&:hover > div:last-child': {
|
||||
backgroundColor: theme.palette.ui03
|
||||
backgroundColor: theme.palette.chatInputBackground
|
||||
}
|
||||
},
|
||||
|
||||
@@ -66,7 +66,7 @@ const useStyles = makeStyles()(theme => {
|
||||
deletedFileMessage: {
|
||||
...theme.typography.bodyShortRegular,
|
||||
fontStyle: 'italic',
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.fileSharingEmptyText,
|
||||
padding: theme.spacing(1, 0)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,14 +39,14 @@ const useStyles = makeStyles()(theme => {
|
||||
}
|
||||
},
|
||||
menuPanel: {
|
||||
backgroundColor: theme.palette.ui03,
|
||||
backgroundColor: theme.palette.chatInputBackground,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
boxShadow: theme.shadows[3],
|
||||
overflow: 'hidden'
|
||||
},
|
||||
copiedMessage: {
|
||||
position: 'fixed',
|
||||
backgroundColor: theme.palette.ui03,
|
||||
backgroundColor: theme.palette.chatInputBackground,
|
||||
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.text01
|
||||
color: theme.palette.chatRecipientText
|
||||
},
|
||||
|
||||
text: {
|
||||
|
||||
@@ -22,7 +22,7 @@ interface IProps extends ISubtitle {
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
messageContainer: {
|
||||
backgroundColor: theme.palette.ui02,
|
||||
backgroundColor: theme.palette.subtitleMessageBackground,
|
||||
borderRadius: '4px 12px 12px 12px',
|
||||
padding: '12px',
|
||||
maxWidth: '100%',
|
||||
@@ -39,7 +39,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
messageHeader: {
|
||||
...theme.typography.labelBold,
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.subtitleMessageSender,
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
overflow: 'hidden',
|
||||
@@ -49,14 +49,14 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
messageText: {
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.subtitleMessageText,
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-word'
|
||||
},
|
||||
|
||||
timestamp: {
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text03,
|
||||
color: theme.palette.subtitleMessageTime,
|
||||
marginTop: theme.spacing(1)
|
||||
},
|
||||
|
||||
|
||||
@@ -33,6 +33,23 @@ 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.
|
||||
|
||||
@@ -14,6 +14,7 @@ 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';
|
||||
@@ -326,6 +327,7 @@ 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.text01,
|
||||
color: theme.palette.conferenceTimerText,
|
||||
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.uiBackground,
|
||||
color: theme.palette.text01,
|
||||
backgroundColor: theme.palette.conferenceNoticeBackground,
|
||||
color: theme.palette.conferenceNoticeText,
|
||||
padding: '3px',
|
||||
borderRadius: '5px'
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
label: {
|
||||
backgroundColor: theme.palette.warning02,
|
||||
color: theme.palette.uiBackground
|
||||
color: theme.palette.conferenceRaisedHandLabelText
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -35,7 +35,7 @@ const RaisedHandsCountLabel = () => {
|
||||
accessibilityText = { t('raisedHandsLabel') }
|
||||
className = { styles.label }
|
||||
icon = { IconRaiseHand }
|
||||
iconColor = { theme.palette.icon04 }
|
||||
iconColor = { theme.palette.conferenceRaisedHandLabelIcon }
|
||||
id = 'raisedHandsCountLabel'
|
||||
onClick = { onClick }
|
||||
text = { `${raisedHandsCount}` } />
|
||||
|
||||
@@ -10,7 +10,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
container: {
|
||||
...theme.typography.bodyLongRegular,
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.conferenceSubjectText,
|
||||
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.text01
|
||||
color: theme.palette.dialogText
|
||||
},
|
||||
|
||||
info: {
|
||||
background: theme.palette.ui01,
|
||||
background: theme.palette.dialogBackground,
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.dialogSecondaryText,
|
||||
marginTop: theme.spacing(2)
|
||||
},
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ const styles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'&.status-lost': {
|
||||
backgroundColor: theme.palette.ui05
|
||||
backgroundColor: theme.palette.connectionIndicatorLost
|
||||
},
|
||||
|
||||
'&.status-other': {
|
||||
|
||||
14
react/features/custom-panel/actionTypes.ts
Normal file
14
react/features/custom-panel/actionTypes.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* 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';
|
||||
40
react/features/custom-panel/actions.web.ts
Normal file
40
react/features/custom-panel/actions.web.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
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
|
||||
};
|
||||
}
|
||||
10
react/features/custom-panel/components/web/CustomPanel.tsx
Normal file
10
react/features/custom-panel/components/web/CustomPanel.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* 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;
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Custom panel button placeholder component.
|
||||
* This file is overridden by jitsi-meet-branding at build time
|
||||
* to provide the actual button implementation with custom icon.
|
||||
*
|
||||
* @returns {null} This placeholder renders nothing.
|
||||
*/
|
||||
const CustomPanelButton = (): null => null;
|
||||
|
||||
export default CustomPanelButton;
|
||||
4
react/features/custom-panel/constants.ts
Normal file
4
react/features/custom-panel/constants.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Default width for the custom panel in pixels.
|
||||
*/
|
||||
export const DEFAULT_CUSTOM_PANEL_WIDTH = 315;
|
||||
67
react/features/custom-panel/functions.ts
Normal file
67
react/features/custom-panel/functions.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { IReduxState } from '../app/types';
|
||||
|
||||
import { DEFAULT_CUSTOM_PANEL_WIDTH } from './constants';
|
||||
|
||||
/**
|
||||
* Returns whether the custom panel is enabled based on Redux state.
|
||||
* The feature is disabled by default and can be enabled dynamically via console.
|
||||
*
|
||||
* @param {IReduxState} state - The Redux state.
|
||||
* @returns {boolean} Whether the custom panel is enabled.
|
||||
*/
|
||||
export function isCustomPanelEnabled(state: IReduxState): boolean {
|
||||
return Boolean(state['features/custom-panel']?.enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the custom panel URL.
|
||||
* Override to provide the actual URL.
|
||||
*
|
||||
* @returns {string} The custom panel URL.
|
||||
*/
|
||||
export function getCustomPanelUrl(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the custom panel button icon.
|
||||
* Override to provide the actual icon.
|
||||
*
|
||||
* @returns {Function | undefined} The icon component.
|
||||
*/
|
||||
export function getCustomPanelIcon(): Function | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured panel width.
|
||||
*
|
||||
* @returns {number} The panel width in pixels.
|
||||
*/
|
||||
export function getCustomPanelConfiguredWidth(): number {
|
||||
return DEFAULT_CUSTOM_PANEL_WIDTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the custom panel is currently open.
|
||||
*
|
||||
* @param {IReduxState} state - The Redux state.
|
||||
* @returns {boolean} Whether the custom panel is open.
|
||||
*/
|
||||
export function getCustomPanelOpen(state: IReduxState): boolean {
|
||||
return Boolean(state['features/custom-panel']?.isOpen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current panel width (0 if closed or disabled).
|
||||
*
|
||||
* @param {IReduxState} state - The Redux state.
|
||||
* @returns {number} The panel width in pixels.
|
||||
*/
|
||||
export function getCustomPanelWidth(state: IReduxState): number {
|
||||
if (!isCustomPanelEnabled(state)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getCustomPanelOpen(state) ? getCustomPanelConfiguredWidth() : 0;
|
||||
}
|
||||
29
react/features/custom-panel/hooks.web.ts
Normal file
29
react/features/custom-panel/hooks.web.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import CustomPanelButton from './components/web/CustomPanelButton';
|
||||
import { isCustomPanelEnabled } from './functions';
|
||||
|
||||
/**
|
||||
* Configuration for the custom panel toolbar button.
|
||||
*/
|
||||
const customPanel = {
|
||||
key: 'custom-panel',
|
||||
Content: CustomPanelButton,
|
||||
group: 2
|
||||
};
|
||||
|
||||
/**
|
||||
* A hook that returns the custom panel button if the feature is enabled.
|
||||
* Uses useSelector for reactive updates when the feature is toggled dynamically.
|
||||
*
|
||||
* @returns {Object | undefined} The button configuration or undefined if disabled.
|
||||
*/
|
||||
export function useCustomPanelButton() {
|
||||
const enabled = useSelector(isCustomPanelEnabled);
|
||||
|
||||
if (enabled) {
|
||||
return customPanel;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
4
react/features/custom-panel/middleware.web.ts
Normal file
4
react/features/custom-panel/middleware.web.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Custom panel middleware placeholder.
|
||||
* Override to add custom panel functionality.
|
||||
*/
|
||||
59
react/features/custom-panel/reducer.ts
Normal file
59
react/features/custom-panel/reducer.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import ReducerRegistry from '../base/redux/ReducerRegistry';
|
||||
|
||||
import {
|
||||
CUSTOM_PANEL_CLOSE,
|
||||
CUSTOM_PANEL_OPEN,
|
||||
SET_CUSTOM_PANEL_ENABLED
|
||||
} from './actionTypes';
|
||||
|
||||
/**
|
||||
* The state of the custom panel feature.
|
||||
*/
|
||||
export interface ICustomPanelState {
|
||||
|
||||
/**
|
||||
* Whether the custom panel feature is enabled.
|
||||
* This can be toggled dynamically via console.
|
||||
*/
|
||||
enabled: boolean;
|
||||
|
||||
/**
|
||||
* Whether the custom panel is currently open.
|
||||
*/
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
const DEFAULT_STATE: ICustomPanelState = {
|
||||
enabled: false,
|
||||
isOpen: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Listen for actions that mutate the custom panel state.
|
||||
*/
|
||||
ReducerRegistry.register(
|
||||
'features/custom-panel', (state: ICustomPanelState = DEFAULT_STATE, action): ICustomPanelState => {
|
||||
switch (action.type) {
|
||||
case CUSTOM_PANEL_CLOSE:
|
||||
return {
|
||||
...state,
|
||||
isOpen: false
|
||||
};
|
||||
|
||||
case CUSTOM_PANEL_OPEN:
|
||||
return {
|
||||
...state,
|
||||
isOpen: true
|
||||
};
|
||||
|
||||
case SET_CUSTOM_PANEL_ENABLED:
|
||||
return {
|
||||
...state,
|
||||
enabled: action.enabled
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -33,12 +33,12 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
contentPane: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
background: theme.palette.ui01,
|
||||
border: `1px solid ${theme.palette.ui03}`,
|
||||
background: theme.palette.deepLinkingBackground,
|
||||
border: `1px solid ${theme.palette.deepLinkingBorder}`,
|
||||
padding: 40,
|
||||
borderRadius: 16,
|
||||
maxWidth: 410,
|
||||
color: theme.palette.text01
|
||||
color: theme.palette.deepLinkingText
|
||||
},
|
||||
logo: {
|
||||
marginBottom: 32
|
||||
@@ -66,14 +66,14 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
marginTop: 40,
|
||||
height: 1,
|
||||
maxWidth: 390,
|
||||
background: theme.palette.ui03
|
||||
background: theme.palette.deepLinkingSeparator
|
||||
},
|
||||
label: {
|
||||
marginTop: 40,
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.deepLinkingLabelText,
|
||||
'& a': {
|
||||
color: theme.palette.link01
|
||||
color: theme.palette.deepLinkingLink
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
flexDirection: 'column',
|
||||
padding: `${PADDINGS.topBottom}px ${PADDINGS.leftRight}px`,
|
||||
maxWidth: 410,
|
||||
color: theme.palette.text01
|
||||
color: theme.palette.deepLinkingText
|
||||
},
|
||||
launchingMeetingLabel: {
|
||||
marginTop: 24,
|
||||
@@ -89,7 +89,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
marginTop: '32px',
|
||||
height: 1,
|
||||
width: `calc(100% + ${2 * PADDINGS.leftRight}px)`,
|
||||
background: theme.palette.ui03
|
||||
background: theme.palette.deepLinkingSeparator
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ const useStyles = makeStyles()(theme => {
|
||||
flex: 1,
|
||||
height: '4px',
|
||||
borderRadius: '1px',
|
||||
backgroundColor: theme.palette.ui04,
|
||||
backgroundColor: theme.palette.labelBackground,
|
||||
marginRight: theme.spacing(1),
|
||||
|
||||
'&:last-of-type': {
|
||||
|
||||
@@ -20,7 +20,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
label: {
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.deviceSelectorText,
|
||||
marginBottom: theme.spacing(2)
|
||||
},
|
||||
|
||||
|
||||
@@ -56,11 +56,11 @@ const useStyles = makeStyles()(theme => {
|
||||
width: '100%',
|
||||
boxSizing: 'border-box',
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
backgroundColor: theme.palette.uiBackground,
|
||||
backgroundColor: theme.palette.deviceSelectorTextBackground,
|
||||
padding: '10px 16px',
|
||||
textAlign: 'center',
|
||||
...theme.typography.bodyShortRegular,
|
||||
border: `1px solid ${theme.palette.ui03}`
|
||||
border: `1px solid ${theme.palette.deviceSelectorBorder}`
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -32,7 +32,7 @@ const useStyles = makeStyles()(theme => {
|
||||
borderRadius: '3px',
|
||||
overflow: 'hidden',
|
||||
marginBottom: theme.spacing(4),
|
||||
backgroundColor: theme.palette.uiBackground
|
||||
backgroundColor: theme.palette.deviceSelectorVideoPreview
|
||||
},
|
||||
|
||||
video: {
|
||||
@@ -42,7 +42,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
errorText: {
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.deviceSelectorText,
|
||||
left: 0,
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
|
||||
@@ -31,7 +31,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
ratingLabel: {
|
||||
...theme.typography.bodyShortBold,
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.dialogText,
|
||||
marginBottom: theme.spacing(2),
|
||||
height: '20px'
|
||||
},
|
||||
|
||||
@@ -84,7 +84,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
fileItem: {
|
||||
backgroundColor: theme.palette.ui02,
|
||||
backgroundColor: theme.palette.fileSharingItemBackground,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
boxSizing: 'border-box',
|
||||
display: 'flex',
|
||||
@@ -106,7 +106,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.ui03,
|
||||
backgroundColor: theme.palette.fileSharingItemBorder,
|
||||
|
||||
'& .actionIconVisibility': {
|
||||
opacity: 1
|
||||
@@ -186,7 +186,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
progressBar: {
|
||||
backgroundColor: theme.palette.ui03,
|
||||
backgroundColor: theme.palette.fileSharingItemBorder,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
height: 4,
|
||||
overflow: 'hidden',
|
||||
@@ -275,7 +275,7 @@ const FileItem = ({
|
||||
<>
|
||||
<div className = { classes.fileIconContainer }>
|
||||
<Icon
|
||||
color = { BaseTheme.palette.icon01 }
|
||||
color = { BaseTheme.palette.fileSharingText }
|
||||
size = { iconSize }
|
||||
src = { getFileIcon(file.fileType) } />
|
||||
</div>
|
||||
@@ -320,7 +320,7 @@ const FileItem = ({
|
||||
onClick = { handleDownload }
|
||||
type = 'button'>
|
||||
<Icon
|
||||
color = { BaseTheme.palette.icon01 }
|
||||
color = { BaseTheme.palette.fileSharingText }
|
||||
size = { 24 }
|
||||
src = { IconDownload } />
|
||||
</button>
|
||||
@@ -335,7 +335,7 @@ const FileItem = ({
|
||||
onClick = { handleRemove }
|
||||
type = 'button'>
|
||||
<Icon
|
||||
color = { BaseTheme.palette.icon01 }
|
||||
color = { BaseTheme.palette.fileSharingText }
|
||||
size = { 24 }
|
||||
src = { IconTrash } />
|
||||
</button>
|
||||
|
||||
@@ -32,8 +32,8 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
dropZone: {
|
||||
backgroundColor: theme.palette.ui02,
|
||||
border: `2px dashed ${theme.palette.ui03}`,
|
||||
backgroundColor: theme.palette.fileSharingItemBackground,
|
||||
border: `2px dashed ${theme.palette.fileSharingItemBorder}`,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
@@ -44,7 +44,7 @@ const useStyles = makeStyles()(theme => {
|
||||
zIndex: 0,
|
||||
|
||||
'&.dragging': {
|
||||
backgroundColor: theme.palette.ui03,
|
||||
backgroundColor: theme.palette.fileSharingItemBorder,
|
||||
borderColor: theme.palette.action01,
|
||||
opacity: 0.8,
|
||||
zIndex: 2
|
||||
@@ -85,7 +85,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
noFilesText: {
|
||||
...theme.typography.bodyLongBold,
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.fileSharingEmptyText,
|
||||
padding: '0 24px',
|
||||
textAlign: 'center'
|
||||
},
|
||||
@@ -189,7 +189,7 @@ const FileSharing = () => {
|
||||
tabIndex = { 0 }>
|
||||
<Icon
|
||||
className = { classes.uploadIcon }
|
||||
color = { BaseTheme.palette.icon03 }
|
||||
color = { BaseTheme.palette.fileSharingEmptyIcon }
|
||||
size = { 160 }
|
||||
src = { IconCloudUpload } />
|
||||
<span className = { classes.noFilesText }>
|
||||
|
||||
@@ -10,7 +10,7 @@ import { withStyles } from 'tss-react/mui';
|
||||
import { ACTION_SHORTCUT_TRIGGERED, createShortcutEvent, createToolbarEvent } from '../../../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../../analytics/functions';
|
||||
import { IReduxState, IStore } from '../../../app/types';
|
||||
import { isMobileBrowser } from '../../../base/environment/utils';
|
||||
import { isMobileBrowser, isTouchDevice, shouldEnableResize } from '../../../base/environment/utils';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconArrowDown, IconArrowUp } from '../../../base/icons/svg';
|
||||
@@ -32,12 +32,17 @@ import {
|
||||
import {
|
||||
ASPECT_RATIO_BREAKPOINT,
|
||||
DEFAULT_FILMSTRIP_WIDTH,
|
||||
DRAG_HANDLE_HEIGHT,
|
||||
DRAG_HANDLE_TOP_PANEL_HEIGHT,
|
||||
DRAG_HANDLE_TOP_PANEL_WIDTH,
|
||||
DRAG_HANDLE_WIDTH,
|
||||
FILMSTRIP_TYPE,
|
||||
MIN_STAGE_VIEW_HEIGHT,
|
||||
MIN_STAGE_VIEW_WIDTH,
|
||||
TILE_HORIZONTAL_MARGIN,
|
||||
TILE_VERTICAL_MARGIN,
|
||||
TOP_FILMSTRIP_HEIGHT
|
||||
TOP_FILMSTRIP_HEIGHT,
|
||||
TOUCH_DRAG_HANDLE_PADDING
|
||||
} from '../../constants';
|
||||
import {
|
||||
getVerticalViewMaxWidth,
|
||||
@@ -52,6 +57,21 @@ import ThumbnailWrapper from './ThumbnailWrapper';
|
||||
|
||||
|
||||
const BACKGROUND_COLOR = 'rgba(51, 51, 51, .5)';
|
||||
const TOUCH_DEVICE_PADDING = {
|
||||
paddingLeft: `${TOUCH_DRAG_HANDLE_PADDING}px`,
|
||||
paddingRight: `${TOUCH_DRAG_HANDLE_PADDING}px`,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0
|
||||
};
|
||||
const TOUCH_DEVICE_TOP_PANEL_PADDING = {
|
||||
paddingLeft: 0,
|
||||
paddingRight: 0,
|
||||
paddingTop: `${TOUCH_DRAG_HANDLE_PADDING}px`,
|
||||
paddingBottom: `${TOUCH_DRAG_HANDLE_PADDING}px`
|
||||
};
|
||||
const NON_TOUCH_DEVICE_PANEL = {
|
||||
pading: 0
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates the styles for the component.
|
||||
@@ -61,6 +81,14 @@ const BACKGROUND_COLOR = 'rgba(51, 51, 51, .5)';
|
||||
* @returns {Object}
|
||||
*/
|
||||
function styles(theme: Theme, props: IProps) {
|
||||
const { _topPanelFilmstrip: isTopPanel } = props;
|
||||
|
||||
const _isTouchDevice = isTouchDevice();
|
||||
const resizeEnabled = shouldEnableResize();
|
||||
const handlePaddding = _isTouchDevice
|
||||
? (isTopPanel ? TOUCH_DEVICE_TOP_PANEL_PADDING : TOUCH_DEVICE_PADDING)
|
||||
: NON_TOUCH_DEVICE_PANEL;
|
||||
|
||||
const result = {
|
||||
toggleFilmstripContainer: {
|
||||
display: 'flex',
|
||||
@@ -79,7 +107,7 @@ function styles(theme: Theme, props: IProps) {
|
||||
zIndex: 1,
|
||||
|
||||
'&:hover, &:focus-within': {
|
||||
backgroundColor: theme.palette.ui02
|
||||
backgroundColor: theme.palette.filmstripBackground
|
||||
}
|
||||
},
|
||||
|
||||
@@ -122,23 +150,27 @@ function styles(theme: Theme, props: IProps) {
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
|
||||
'&:hover, &:focus-within': {
|
||||
'& .resizable-filmstrip': {
|
||||
backgroundColor: BACKGROUND_COLOR
|
||||
},
|
||||
// On touch devices, handle is always visible via base styles, so no hover needed.
|
||||
// On desktop, show handle on hover/focus.
|
||||
...(!_isTouchDevice && {
|
||||
'&:hover, &:focus-within': {
|
||||
'& .resizable-filmstrip': {
|
||||
backgroundColor: BACKGROUND_COLOR
|
||||
},
|
||||
|
||||
'& .filmstrip-hover': {
|
||||
backgroundColor: BACKGROUND_COLOR
|
||||
},
|
||||
'& .filmstrip-hover': {
|
||||
backgroundColor: BACKGROUND_COLOR
|
||||
},
|
||||
|
||||
'& .toggleFilmstripContainer': {
|
||||
opacity: 1
|
||||
},
|
||||
'& .toggleFilmstripContainer': {
|
||||
opacity: 1
|
||||
},
|
||||
|
||||
'& .dragHandleContainer': {
|
||||
visibility: 'visible' as const
|
||||
'& .dragHandleContainer': {
|
||||
visibility: 'visible' as const
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
'.horizontal-filmstrip &.hidden': {
|
||||
bottom: '-50px',
|
||||
@@ -156,10 +188,10 @@ function styles(theme: Theme, props: IProps) {
|
||||
},
|
||||
|
||||
filmstripBackground: {
|
||||
backgroundColor: theme.palette.uiBackground,
|
||||
backgroundColor: theme.palette.filmstripBackgroundHover,
|
||||
|
||||
'&:hover, &:focus-within': {
|
||||
backgroundColor: theme.palette.uiBackground
|
||||
backgroundColor: theme.palette.filmstripBackgroundHover
|
||||
}
|
||||
},
|
||||
|
||||
@@ -187,18 +219,26 @@ function styles(theme: Theme, props: IProps) {
|
||||
|
||||
dragHandleContainer: {
|
||||
height: '100%',
|
||||
width: '9px',
|
||||
width: `${DRAG_HANDLE_WIDTH}px`,
|
||||
backgroundColor: 'transparent',
|
||||
position: 'relative' as const,
|
||||
cursor: 'col-resize',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
visibility: 'hidden' as const,
|
||||
// On touch devices, always visible if resize enabled. On desktop, hidden by default
|
||||
visibility: (_isTouchDevice && resizeEnabled) ? 'visible' as const : 'hidden' as const,
|
||||
marginLeft: 0,
|
||||
marginTop: 0,
|
||||
// Touch devices get padding for easier tapping
|
||||
// Vertical filmstrip: left/right padding. Top panel: top/bottom padding.
|
||||
...handlePaddding,
|
||||
// Prevent touch scrolling while dragging
|
||||
touchAction: 'none',
|
||||
|
||||
'&:hover': {
|
||||
'& .dragHandle': {
|
||||
backgroundColor: theme.palette.icon01
|
||||
backgroundColor: theme.palette.filmstripDragHandleHover
|
||||
}
|
||||
},
|
||||
|
||||
@@ -206,27 +246,28 @@ function styles(theme: Theme, props: IProps) {
|
||||
visibility: 'visible' as const,
|
||||
|
||||
'& .dragHandle': {
|
||||
backgroundColor: theme.palette.icon01
|
||||
backgroundColor: theme.palette.filmstripDragHandleHover
|
||||
}
|
||||
},
|
||||
|
||||
'&.top-panel': {
|
||||
order: 2,
|
||||
width: '100%',
|
||||
height: '9px',
|
||||
height: `${DRAG_HANDLE_WIDTH}px`,
|
||||
cursor: 'row-resize',
|
||||
|
||||
'& .dragHandle': {
|
||||
height: '3px',
|
||||
width: '100px'
|
||||
height: `${DRAG_HANDLE_TOP_PANEL_HEIGHT}px`,
|
||||
width: `${DRAG_HANDLE_TOP_PANEL_WIDTH}px`
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dragHandle: {
|
||||
backgroundColor: theme.palette.icon02,
|
||||
height: '100px',
|
||||
width: '3px',
|
||||
// Keep the same visual appearance on all devices
|
||||
backgroundColor: theme.palette.filmstripDragHandle,
|
||||
height: `${DRAG_HANDLE_HEIGHT}px`,
|
||||
width: `${DRAG_HANDLE_WIDTH / 3}px`,
|
||||
borderRadius: '1px'
|
||||
}
|
||||
};
|
||||
@@ -313,6 +354,11 @@ export interface IProps extends WithTranslation {
|
||||
*/
|
||||
_isToolboxVisible: Boolean;
|
||||
|
||||
/**
|
||||
* Whether the device has touch capability.
|
||||
*/
|
||||
_isTouchDevice?: boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the current layout is vertical filmstrip.
|
||||
*/
|
||||
@@ -358,6 +404,11 @@ export interface IProps extends WithTranslation {
|
||||
*/
|
||||
_resizableFilmstrip: boolean;
|
||||
|
||||
/**
|
||||
* Whether resize functionality should be enabled based on device and screen size.
|
||||
*/
|
||||
_resizeEnabled?: boolean;
|
||||
|
||||
/**
|
||||
* The number of rows in tile view.
|
||||
*/
|
||||
@@ -491,8 +542,10 @@ class Filmstrip extends PureComponent <IProps, IState> {
|
||||
this._onGridItemsRendered = this._onGridItemsRendered.bind(this);
|
||||
this._onListItemsRendered = this._onListItemsRendered.bind(this);
|
||||
this._onToggleButtonTouch = this._onToggleButtonTouch.bind(this);
|
||||
this._onDragHandleMouseDown = this._onDragHandleMouseDown.bind(this);
|
||||
this._onDragMouseUp = this._onDragMouseUp.bind(this);
|
||||
this._onDragHandlePointerDown = this._onDragHandlePointerDown.bind(this);
|
||||
this._onDragHandleClick = this._onDragHandleClick.bind(this);
|
||||
this._onDragHandleTouchStart = this._onDragHandleTouchStart.bind(this);
|
||||
this._onDragPointerUp = this._onDragPointerUp.bind(this);
|
||||
this._onFilmstripResize = this._onFilmstripResize.bind(this);
|
||||
|
||||
this._throttledResize = throttle(
|
||||
@@ -516,10 +569,10 @@ class Filmstrip extends PureComponent <IProps, IState> {
|
||||
handler: this._onShortcutToggleFilmstrip
|
||||
}));
|
||||
|
||||
document.addEventListener('mouseup', this._onDragMouseUp);
|
||||
document.addEventListener('pointerup', this._onDragPointerUp);
|
||||
|
||||
// @ts-ignore
|
||||
document.addEventListener('mousemove', this._throttledResize);
|
||||
document.addEventListener('pointermove', this._throttledResize);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -530,10 +583,10 @@ class Filmstrip extends PureComponent <IProps, IState> {
|
||||
override componentWillUnmount() {
|
||||
this.props.dispatch(unregisterShortcut('F'));
|
||||
|
||||
document.removeEventListener('mouseup', this._onDragMouseUp);
|
||||
document.removeEventListener('pointerup', this._onDragPointerUp);
|
||||
|
||||
// @ts-ignore
|
||||
document.removeEventListener('mousemove', this._throttledResize);
|
||||
document.removeEventListener('pointermove', this._throttledResize);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -678,7 +731,9 @@ class Filmstrip extends PureComponent <IProps, IState> {
|
||||
(isMouseDown || _alwaysShowResizeBar) && 'visible',
|
||||
_topPanelFilmstrip && 'top-panel')
|
||||
}
|
||||
onMouseDown = { this._onDragHandleMouseDown }>
|
||||
onClick = { this._onDragHandleClick }
|
||||
onPointerDown = { this._onDragHandlePointerDown }
|
||||
onTouchStart = { this._onDragHandleTouchStart }>
|
||||
<div className = { clsx(classes.dragHandle, 'dragHandle') } />
|
||||
</div>
|
||||
{filmstrip}
|
||||
@@ -691,14 +746,23 @@ class Filmstrip extends PureComponent <IProps, IState> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles mouse down on the drag handle.
|
||||
* Handles pointer down on the drag handle.
|
||||
* Supports both mouse and touch events via Pointer Events API.
|
||||
*
|
||||
* @param {MouseEvent} e - The mouse down event.
|
||||
* @param {React.PointerEvent} e - The pointer down event.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onDragHandleMouseDown(e: React.MouseEvent) {
|
||||
_onDragHandlePointerDown(e: React.PointerEvent) {
|
||||
const { _topPanelFilmstrip, _topPanelHeight, _verticalFilmstripWidth } = this.props;
|
||||
|
||||
// Prevent toolbar from appearing and stop event propagation
|
||||
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);
|
||||
|
||||
this.setState({
|
||||
isMouseDown: true,
|
||||
mousePosition: _topPanelFilmstrip ? e.clientY : e.clientX,
|
||||
@@ -709,11 +773,33 @@ class Filmstrip extends PureComponent <IProps, IState> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Drag handle mouse up handler.
|
||||
* Prevents click events on drag handle from triggering toolbar.
|
||||
*
|
||||
* @param {React.MouseEvent} e - The click event.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onDragHandleClick(e: React.MouseEvent) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents touch start events on drag handle from triggering toolbar.
|
||||
*
|
||||
* @param {React.TouchEvent} e - The touch start event.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onDragHandleTouchStart(e: React.TouchEvent) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Drag handle pointer up handler.
|
||||
* Supports both mouse and touch events via Pointer Events API.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onDragMouseUp() {
|
||||
_onDragPointerUp() {
|
||||
if (this.state.isMouseDown) {
|
||||
this.setState({
|
||||
isMouseDown: false
|
||||
@@ -723,12 +809,13 @@ class Filmstrip extends PureComponent <IProps, IState> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles drag handle mouse move.
|
||||
* Handles drag handle pointer move.
|
||||
* Supports both mouse and touch events via Pointer Events API.
|
||||
*
|
||||
* @param {MouseEvent} e - The mousemove event.
|
||||
* @param {PointerEvent} e - The pointermove event.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onFilmstripResize(e: React.MouseEvent) {
|
||||
_onFilmstripResize(e: PointerEvent) {
|
||||
if (this.state.isMouseDown) {
|
||||
const {
|
||||
dispatch,
|
||||
@@ -1163,4 +1250,4 @@ function _mapStateToProps(state: IReduxState, ownProps: any) {
|
||||
};
|
||||
}
|
||||
|
||||
export default withStyles(translate(connect(_mapStateToProps)(Filmstrip)), styles);
|
||||
export default translate(connect(_mapStateToProps)(withStyles(Filmstrip, styles)));
|
||||
|
||||
@@ -67,7 +67,7 @@ const RaisedHandIndicator = ({
|
||||
<div className = { styles.raisedHandIndicator }>
|
||||
<BaseIndicator
|
||||
icon = { IconRaiseHand }
|
||||
iconColor = { theme.palette.uiBackground }
|
||||
iconColor = { theme.palette.thumbnailRaisedHandIcon }
|
||||
iconSize = { iconSize }
|
||||
tooltipKey = 'raisedHand'
|
||||
tooltipPosition = { tooltipPosition } />
|
||||
|
||||
@@ -305,7 +305,7 @@ const defaultStyles = (theme: Theme) => {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
borderRadius: '4px',
|
||||
backgroundColor: theme.palette.ui02
|
||||
backgroundColor: theme.palette.thumbnailBackground
|
||||
},
|
||||
|
||||
borderIndicator: {
|
||||
@@ -341,7 +341,7 @@ const defaultStyles = (theme: Theme) => {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
overflow: 'hidden',
|
||||
backgroundColor: theme.palette.ui02,
|
||||
backgroundColor: theme.palette.thumbnailBackground,
|
||||
|
||||
'& img': {
|
||||
maxWidth: '100%',
|
||||
@@ -356,7 +356,7 @@ const defaultStyles = (theme: Theme) => {
|
||||
zIndex: 1,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
backgroundColor: `${theme.palette.uiBackground}`,
|
||||
backgroundColor: theme.palette.thumbnailTintBackground,
|
||||
opacity: 0.8
|
||||
},
|
||||
|
||||
|
||||
@@ -269,6 +269,19 @@ export const MIN_STAGE_VIEW_HEIGHT = 700;
|
||||
*/
|
||||
export const MIN_STAGE_VIEW_WIDTH = 800;
|
||||
|
||||
/**
|
||||
* Drag handle dimensions for resizable filmstrip.
|
||||
*/
|
||||
export const DRAG_HANDLE_WIDTH = 9;
|
||||
export const DRAG_HANDLE_HEIGHT = 100;
|
||||
export const DRAG_HANDLE_TOP_PANEL_HEIGHT = 3;
|
||||
export const DRAG_HANDLE_TOP_PANEL_WIDTH = 100;
|
||||
|
||||
/**
|
||||
* Touch padding added to each side of drag handle for easier tapping on touch devices.
|
||||
*/
|
||||
export const TOUCH_DRAG_HANDLE_PADDING = 6;
|
||||
|
||||
/**
|
||||
* Horizontal margin used for the vertical filmstrip.
|
||||
*/
|
||||
@@ -298,3 +311,9 @@ export const MAX_ACTIVE_PARTICIPANTS = 6;
|
||||
* Top filmstrip default height.
|
||||
*/
|
||||
export const TOP_FILMSTRIP_HEIGHT = 180;
|
||||
|
||||
/**
|
||||
* Minimum screen width needed for functional filmstrip resizing.
|
||||
* Calculated as stage minimum + filmstrip minimum (800px + 120px = 920px).
|
||||
*/
|
||||
export const MIN_FILMSTRIP_RESIZE_WIDTH = MIN_STAGE_VIEW_WIDTH + DEFAULT_FILMSTRIP_WIDTH;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Theme } from '@mui/material/styles';
|
||||
|
||||
import { IReduxState } from '../app/types';
|
||||
import { IStateful } from '../base/app/types';
|
||||
import { isMobileBrowser } from '../base/environment/utils';
|
||||
import { isTouchDevice, shouldEnableResize } from '../base/environment/utils';
|
||||
import { MEDIA_TYPE } from '../base/media/constants';
|
||||
import {
|
||||
getLocalParticipant,
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
DEFAULT_LOCAL_TILE_ASPECT_RATIO,
|
||||
DISPLAY_AVATAR,
|
||||
DISPLAY_VIDEO,
|
||||
DRAG_HANDLE_WIDTH,
|
||||
FILMSTRIP_GRID_BREAKPOINT,
|
||||
FILMSTRIP_TYPE,
|
||||
INDICATORS_TOOLTIP_POSITION,
|
||||
@@ -45,6 +46,7 @@ import {
|
||||
TILE_VIEW_DEFAULT_NUMBER_OF_VISIBLE_TILES,
|
||||
TILE_VIEW_GRID_HORIZONTAL_MARGIN,
|
||||
TILE_VIEW_GRID_VERTICAL_MARGIN,
|
||||
TOUCH_DRAG_HANDLE_PADDING,
|
||||
VERTICAL_VIEW_HORIZONTAL_MARGIN
|
||||
} from './constants';
|
||||
|
||||
@@ -621,6 +623,7 @@ export function getIndicatorsTooltipPosition(thumbnailType?: string) {
|
||||
|
||||
/**
|
||||
* Returns whether or not the filmstrip is resizable.
|
||||
* On touch devices, resize is only enabled for larger screens (tablets, not phones).
|
||||
*
|
||||
* @param {Object} state - Redux state.
|
||||
* @returns {boolean}
|
||||
@@ -629,7 +632,7 @@ export function isFilmstripResizable(state: IReduxState) {
|
||||
const { filmstrip } = state['features/base/config'];
|
||||
const _currentLayout = getCurrentLayout(state);
|
||||
|
||||
return !filmstrip?.disableResizable && !isMobileBrowser()
|
||||
return !filmstrip?.disableResizable && shouldEnableResize()
|
||||
&& (_currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW || _currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW);
|
||||
}
|
||||
|
||||
@@ -662,8 +665,13 @@ export function getVerticalViewMaxWidth(state: IReduxState) {
|
||||
|
||||
// Adding 4px for the border-right and margin-right.
|
||||
// On non-resizable filmstrip add 4px for the left margin and border.
|
||||
// Also adding 7px for the scrollbar. Also adding 9px for the drag handle.
|
||||
maxWidth += (_verticalViewGrid ? 0 : 11) + (_resizableFilmstrip ? 9 : 4);
|
||||
// Also adding 7px for the scrollbar.
|
||||
// Drag handle: DRAG_HANDLE_WIDTH + padding (TOUCH_DRAG_HANDLE_PADDING on each side for touch)
|
||||
const dragHandleWidth = isTouchDevice()
|
||||
? DRAG_HANDLE_WIDTH + (TOUCH_DRAG_HANDLE_PADDING * 2)
|
||||
: DRAG_HANDLE_WIDTH;
|
||||
|
||||
maxWidth += (_verticalViewGrid ? 0 : 11) + (_resizableFilmstrip ? dragHandleWidth : 4);
|
||||
|
||||
return maxWidth;
|
||||
}
|
||||
@@ -840,5 +848,5 @@ export function isTopPanelEnabled(state: IReduxState) {
|
||||
* @returns {string} The background color.
|
||||
*/
|
||||
export function getThumbnailBackgroundColor(theme: Theme): string {
|
||||
return theme.palette.uiBackground;
|
||||
return theme.palette.thumbnailVideoBackground;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
marginTop: 32,
|
||||
maxWidth: 310,
|
||||
padding: '16px 12px',
|
||||
background: theme.palette.ui02,
|
||||
background: theme.palette.dialInBackground,
|
||||
textAlign: 'center',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
@@ -50,7 +50,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
separator: {
|
||||
width: '100%',
|
||||
height: 1,
|
||||
background: theme.palette.ui04,
|
||||
background: theme.palette.labelBackground,
|
||||
marginBottom: 18
|
||||
},
|
||||
pinLabel: {
|
||||
|
||||
@@ -94,7 +94,7 @@ const styles = (theme: Theme) => {
|
||||
display: 'flex',
|
||||
flexDirection: 'column' as const,
|
||||
background: '#1E1E1E',
|
||||
color: theme.palette.text01
|
||||
color: theme.palette.dialInText
|
||||
},
|
||||
scrollable: {
|
||||
height: '100dvh',
|
||||
|
||||
@@ -11,7 +11,7 @@ const useStyles = makeStyles()(theme => {
|
||||
overlayContainer: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
backgroundColor: theme.palette.ui02,
|
||||
backgroundColor: theme.palette.largeVideoPlaceholder,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
@@ -31,13 +31,13 @@ const useStyles = makeStyles()(theme => {
|
||||
height: '56px',
|
||||
boxSizing: 'border-box',
|
||||
border: '3px solid',
|
||||
borderColor: theme.palette.text01,
|
||||
borderColor: theme.palette.dialogText,
|
||||
borderRadius: '6px'
|
||||
},
|
||||
laptopStand: {
|
||||
width: '40px',
|
||||
height: '4px',
|
||||
backgroundColor: theme.palette.text01,
|
||||
backgroundColor: theme.palette.dialogText,
|
||||
boxSizing: 'border-box',
|
||||
borderRadius: '6px',
|
||||
marginTop: '4px'
|
||||
@@ -49,7 +49,7 @@ const useStyles = makeStyles()(theme => {
|
||||
lineHeight: '1.75rem',
|
||||
marginTop: '24px',
|
||||
letterSpacing: '-0.012em',
|
||||
color: theme.palette.text01
|
||||
color: theme.palette.dialogText
|
||||
},
|
||||
showSharing: {
|
||||
fontStyle: 'normal',
|
||||
|
||||
@@ -39,7 +39,7 @@ interface IProps extends INotificationProps {
|
||||
const useStyles = makeStyles()((theme: Theme) => {
|
||||
return {
|
||||
container: {
|
||||
backgroundColor: theme.palette.ui10,
|
||||
backgroundColor: theme.palette.notificationBackground,
|
||||
padding: '8px 16px 8px 20px',
|
||||
display: 'flex',
|
||||
position: 'relative' as const,
|
||||
@@ -85,19 +85,19 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
borderRadius: '4px',
|
||||
|
||||
'&.normal': {
|
||||
backgroundColor: theme.palette.action01
|
||||
backgroundColor: theme.palette.notificationNormalIcon
|
||||
},
|
||||
|
||||
'&.error': {
|
||||
backgroundColor: theme.palette.iconError
|
||||
backgroundColor: theme.palette.notificationError
|
||||
},
|
||||
|
||||
'&.success': {
|
||||
backgroundColor: theme.palette.success01
|
||||
backgroundColor: theme.palette.notificationSuccess
|
||||
},
|
||||
|
||||
'&.warning': {
|
||||
backgroundColor: theme.palette.warning01
|
||||
backgroundColor: theme.palette.notificationWarning
|
||||
}
|
||||
},
|
||||
|
||||
@@ -113,7 +113,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
display: 'flex',
|
||||
flexDirection: 'column' as const,
|
||||
justifyContent: 'space-between',
|
||||
color: theme.palette.text04,
|
||||
color: theme.palette.notificationText,
|
||||
flex: 1,
|
||||
margin: '0 8px',
|
||||
|
||||
@@ -150,7 +150,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
border: 0,
|
||||
outline: 0,
|
||||
backgroundColor: 'transparent',
|
||||
color: theme.palette.action01,
|
||||
color: theme.palette.notificationActionText,
|
||||
...theme.typography.bodyShortBold,
|
||||
marginRight: theme.spacing(3),
|
||||
padding: 0,
|
||||
@@ -161,11 +161,11 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
|
||||
'&.destructive': {
|
||||
color: theme.palette.textError
|
||||
color: theme.palette.notificationErrorText
|
||||
},
|
||||
|
||||
'&:focus-visible': {
|
||||
outline: `2px solid ${theme.palette.action01}`,
|
||||
outline: `2px solid ${theme.palette.notificationActionFocus}`,
|
||||
outlineOffset: 2
|
||||
}
|
||||
},
|
||||
@@ -203,10 +203,10 @@ const Notification = ({
|
||||
);
|
||||
|
||||
const ICON_COLOR = {
|
||||
error: theme.palette.iconError,
|
||||
normal: theme.palette.action01,
|
||||
success: theme.palette.success01,
|
||||
warning: theme.palette.warning01
|
||||
error: theme.palette.notificationError,
|
||||
normal: theme.palette.notificationNormalIcon,
|
||||
success: theme.palette.notificationSuccess,
|
||||
warning: theme.palette.notificationWarning
|
||||
};
|
||||
|
||||
const onDismiss = useCallback(() => {
|
||||
@@ -359,10 +359,10 @@ const Notification = ({
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{ !disableClosing && (
|
||||
{!disableClosing && (
|
||||
<Icon
|
||||
className = { classes.closeIcon }
|
||||
color = { theme.palette.icon04 }
|
||||
color = { theme.palette.notificationCloseIcon }
|
||||
id = 'close-notification'
|
||||
onClick = { onDismiss }
|
||||
size = { 20 }
|
||||
|
||||
@@ -95,7 +95,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
arrowContainer: {
|
||||
backgroundColor: theme.palette.ui03,
|
||||
backgroundColor: theme.palette.breakoutRoomArrowBackground,
|
||||
width: '24px',
|
||||
height: '24px',
|
||||
borderRadius: '6px',
|
||||
|
||||
@@ -49,7 +49,7 @@ interface IProps {
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
text: {
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.participantSectionText,
|
||||
padding: '10px 16px',
|
||||
height: '40px',
|
||||
overflow: 'hidden',
|
||||
|
||||
@@ -45,11 +45,11 @@ const useStyles = makeStyles()(theme => {
|
||||
cursor: 'pointer',
|
||||
padding: `${theme.spacing(1)} 0`,
|
||||
...theme.typography.bodyShortBold,
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.participantSectionText,
|
||||
flexShrink: 0
|
||||
},
|
||||
arrowContainer: {
|
||||
backgroundColor: theme.palette.ui03,
|
||||
backgroundColor: theme.palette.visitorsArrowBackground,
|
||||
width: '24px',
|
||||
height: '24px',
|
||||
borderRadius: '6px',
|
||||
|
||||
@@ -56,7 +56,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
text: {
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.participantSectionText,
|
||||
padding: '10px 16px',
|
||||
height: '40px',
|
||||
overflow: 'hidden',
|
||||
|
||||
@@ -24,7 +24,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
drawerItem: {
|
||||
alignItems: 'center',
|
||||
color: theme.palette.text01,
|
||||
color: theme.palette.participantCounterText,
|
||||
display: 'flex',
|
||||
padding: '12px 16px',
|
||||
...theme.typography.bodyShortRegularLarge,
|
||||
@@ -35,7 +35,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
'&:hover': {
|
||||
cursor: 'pointer',
|
||||
background: theme.palette.action02
|
||||
background: theme.palette.participantActionButton
|
||||
}
|
||||
},
|
||||
icon: {
|
||||
@@ -48,11 +48,11 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
heading: {
|
||||
...theme.typography.bodyShortBold,
|
||||
color: theme.palette.text02
|
||||
color: theme.palette.participantSectionText
|
||||
},
|
||||
link: {
|
||||
...theme.typography.labelBold,
|
||||
color: theme.palette.link01,
|
||||
color: theme.palette.participantLinkText,
|
||||
cursor: 'pointer'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,10 +23,10 @@ import MeetingParticipantItems from './MeetingParticipantItems';
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
headingW: {
|
||||
color: theme.palette.warning02
|
||||
color: theme.palette.participantWarningText
|
||||
},
|
||||
heading: {
|
||||
color: theme.palette.text02,
|
||||
color: theme.palette.participantSectionText,
|
||||
...theme.typography.bodyShortBold,
|
||||
marginBottom: theme.spacing(3),
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
moderatorLabel: {
|
||||
...theme.typography.labelBold,
|
||||
color: theme.palette.text03
|
||||
color: theme.palette.participantModeratorLabel
|
||||
},
|
||||
|
||||
avatar: {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user