Merge pull request #10390 from vitormateusalmeida/debug-window

Add Debug window
This commit is contained in:
Anton Georgiev 2020-12-08 16:17:26 -05:00 committed by GitHub
commit 373e6b9dec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 326 additions and 51 deletions

View File

@ -21,6 +21,7 @@ import getFromUserSettings from '/imports/ui/services/users-settings';
import LayoutManager from '/imports/ui/components/layout/layout-manager'; import LayoutManager from '/imports/ui/components/layout/layout-manager';
import { withLayoutContext } from '/imports/ui/components/layout/context'; import { withLayoutContext } from '/imports/ui/components/layout/context';
import VideoService from '/imports/ui/components/video-provider/service'; import VideoService from '/imports/ui/components/video-provider/service';
import DebugWindow from '/imports/ui/components/debug-window/component'
import {Meteor} from "meteor/meteor"; import {Meteor} from "meteor/meteor";
const CHAT_CONFIG = Meteor.settings.public.chat; const CHAT_CONFIG = Meteor.settings.public.chat;
@ -229,7 +230,8 @@ class Base extends Component {
return ( return (
<Fragment> <Fragment>
<LayoutManager /> {meetingExist && Auth.loggedIn && <DebugWindow />}
{meetingExist && Auth.loggedIn && <LayoutManager />}
{ {
(!meetingExisted && !meetingExist && Auth.loggedIn) (!meetingExisted && !meetingExist && Auth.loggedIn)
? <LoadingScreen /> ? <LoadingScreen />

View File

@ -7,38 +7,9 @@ import AudioControlsContainer from '../audio/audio-controls/container';
import JoinVideoOptionsContainer from '../video-provider/video-button/container'; import JoinVideoOptionsContainer from '../video-provider/video-button/container';
import CaptionsButtonContainer from '/imports/ui/components/actions-bar/captions/container'; import CaptionsButtonContainer from '/imports/ui/components/actions-bar/captions/container';
import PresentationOptionsContainer from './presentation-options/component'; import PresentationOptionsContainer from './presentation-options/component';
import Button from '/imports/ui/components/button/component';
import Storage from '/imports/ui/services/storage/session';
import { ACTIONSBAR_HEIGHT } from '/imports/ui/components/layout/layout-manager'; import { ACTIONSBAR_HEIGHT } from '/imports/ui/components/layout/layout-manager';
import { withLayoutConsumer } from '/imports/ui/components/layout/context';
class ActionsBar extends PureComponent { class ActionsBar extends PureComponent {
constructor(props) {
super(props);
this.autoArrangeToggle = this.autoArrangeToggle.bind(this);
}
componentDidUpdate(prevProps) {
const { layoutContextState } = this.props;
const { layoutContextState: prevLayoutContextState } = prevProps;
const { autoArrangeLayout } = layoutContextState;
const { autoArrangeLayout: prevAutoArrangeLayout } = prevLayoutContextState;
if (autoArrangeLayout !== prevAutoArrangeLayout) this.forceUpdate();
}
autoArrangeToggle() {
const { layoutContextDispatch } = this.props;
const autoArrangeLayout = Storage.getItem('autoArrangeLayout');
layoutContextDispatch(
{
type: 'setAutoArrangeLayout',
value: !autoArrangeLayout,
},
);
window.dispatchEvent(new Event('autoArrangeChanged'));
}
render() { render() {
const { const {
amIPresenter, amIPresenter,
@ -52,8 +23,6 @@ class ActionsBar extends PureComponent {
toggleSwapLayout, toggleSwapLayout,
handleTakePresenter, handleTakePresenter,
intl, intl,
currentSlidHasContent,
parseCurrentSlideContent,
isSharingVideo, isSharingVideo,
screenShareEndAlert, screenShareEndAlert,
stopExternalVideoShare, stopExternalVideoShare,
@ -66,7 +35,6 @@ class ActionsBar extends PureComponent {
} = this.props; } = this.props;
const actionBarClasses = {}; const actionBarClasses = {};
const autoArrangeLayout = Storage.getItem('autoArrangeLayout');
actionBarClasses[styles.centerWithActions] = amIPresenter; actionBarClasses[styles.centerWithActions] = amIPresenter;
actionBarClasses[styles.center] = true; actionBarClasses[styles.center] = true;
@ -117,18 +85,6 @@ class ActionsBar extends PureComponent {
screenshareDataSavingSetting, screenshareDataSavingSetting,
}} }}
/> />
<Button
className={cx(styles.btn, autoArrangeLayout || styles.btn)}
icon={autoArrangeLayout ? 'lock' : 'unlock'}
color={autoArrangeLayout ? 'primary' : 'default'}
ghost={!autoArrangeLayout}
onClick={this.autoArrangeToggle}
label={autoArrangeLayout ? 'Disable Auto Arrange' : 'Enable Auto Arrange'}
aria-label="Auto Arrange test"
hideLabel
circle
size="lg"
/>
</div> </div>
<div className={styles.right}> <div className={styles.right}>
{isLayoutSwapped {isLayoutSwapped
@ -146,4 +102,4 @@ class ActionsBar extends PureComponent {
} }
} }
export default withLayoutConsumer(ActionsBar); export default ActionsBar;

View File

@ -0,0 +1,203 @@
import React, { Component } from 'react';
import Draggable from 'react-draggable';
import Resizable from 're-resizable';
import { styles } from './styles.scss';
import { defineMessages, injectIntl } from 'react-intl';
import Icon from '/imports/ui/components/icon/component';
import Button from '/imports/ui/components/button/component';
import Toggle from '/imports/ui/components/switch/component';
import Storage from '/imports/ui/services/storage/session';
import { withLayoutConsumer } from '/imports/ui/components/layout/context';
const intlMessages = defineMessages({
modalClose: {
id: 'app.modal.close',
description: 'Close',
},
modalCloseDescription: {
id: 'app.modal.close.description',
description: 'Disregards changes and closes the modal',
},
debugWindowTitle: {
id: 'app.debugWindow.windowTitle',
description: 'Debug window title',
},
userAgentLabel: {
id: 'app.debugWindow.form.userAgentLabel',
description: 'User agent form label',
},
copyButtonLabel: {
id: 'app.debugWindow.form.button.copy',
description: 'User agent form copy button',
},
enableAutoarrangeLayoutLabel: {
id: 'app.debugWindow.form.enableAutoarrangeLayoutLabel',
description: 'Enable Autoarrange layout label',
},
enableAutoarrangeLayoutDescription: {
id: 'app.debugWindow.form.enableAutoarrangeLayoutDescription',
description: 'Enable Autoarrange layout description',
},
});
const DEBUG_WINDOW_ENABLED = Meteor.settings.public.app.enableDebugWindow;
const SHOW_DEBUG_WINDOW_ACCESSKEY = Meteor.settings.public.app.shortcuts.openDebugWindow.accesskey;
class DebugWindow extends Component {
constructor(props) {
super(props);
this.state = {
showDebugWindow: false,
};
}
componentDidMount() {
document.addEventListener('keyup', (event) => {
const key = event.key.toUpperCase();
if (DEBUG_WINDOW_ENABLED && event.altKey && key === SHOW_DEBUG_WINDOW_ACCESSKEY) {
this.debugWindowToggle();
}
});
}
setShowDebugWindow(showDebugWindow) {
this.setState({ showDebugWindow });
}
debugWindowToggle() {
const { showDebugWindow } = this.state;
if (showDebugWindow) {
this.setShowDebugWindow(false);
} else {
this.setShowDebugWindow(true);
}
}
autoArrangeToggle() {
const { layoutContextDispatch } = this.props;
const autoArrangeLayout = Storage.getItem('autoArrangeLayout');
layoutContextDispatch(
{
type: 'setAutoArrangeLayout',
value: !autoArrangeLayout,
},
);
window.dispatchEvent(new Event('autoArrangeChanged'));
}
render() {
const { showDebugWindow } = this.state;
if (!DEBUG_WINDOW_ENABLED || !showDebugWindow) return false;
const { intl } = this.props;
const autoArrangeLayout = Storage.getItem('autoArrangeLayout');
return (
<Draggable
handle="#debugWindowHeader"
bounds="body"
// onStart={}
// onStop={}
// disabled={}
// position={}
enableUserSelectHack={false}
>
<Resizable
className={styles.debugWindowWrapper}
minWidth={window.innerWidth * 0.2}
minHeight={window.innerHeight * 0.2}
// size={
// {
// width: sizeWidth,
// height: sizeHeight,
// }
// }
// lockAspectRatio
// handleWrapperClass="resizeWrapper"
// onResizeStart={}
// onResize={}
// onResizeStop={(e, direction, ref, d) => {
// this.setWebcamsAreaResizable(d.width, d.height);
// }}
enable={{
top: false,
bottom: false,
left: false,
right: false,
topLeft: false,
topRight: false,
bottomLeft: false,
bottomRight: true,
}}
>
<div
className={styles.debugWindow}
>
<div
id="debugWindowHeader"
className={styles.header}
>
<Icon iconName="fit_to_screen" className={styles.moveIcon} />
<div className={styles.title}>
{intl.formatMessage(intlMessages.debugWindowTitle)}
</div>
<Button
className={styles.close}
label={intl.formatMessage(intlMessages.modalClose)}
aria-label={`${intl.formatMessage(intlMessages.modalClose)} ${intl.formatMessage(intlMessages.debugWindowTitle)}`}
icon="close"
circle
hideLabel
onClick={() => this.setShowDebugWindow(false)}
/>
</div>
<div className={styles.debugWindowContent}>
<div className={styles.table}>
<div className={styles.row}>
<div className={styles.cell}>
{`${intl.formatMessage(intlMessages.userAgentLabel)}:`}
</div>
<div className={styles.cell}>
<input
className={styles.userAgentInput}
id="debugModalUserAgent"
type="text"
value={window.navigator.userAgent}
readOnly
/>
<button
type="button"
onClick={() => navigator.clipboard.writeText(window.navigator.userAgent)}
>
{`${intl.formatMessage(intlMessages.copyButtonLabel)}`}
</button>
</div>
</div>
<div className={styles.row}>
<div className={styles.cell}>
{`${intl.formatMessage(intlMessages.enableAutoarrangeLayoutLabel)}:`}
</div>
<div className={styles.cell}>
<div className={styles.cellContent}>
<Toggle
className={styles.autoArrangeToggle}
icons={false}
defaultChecked={autoArrangeLayout}
onChange={() => this.autoArrangeToggle()}
ariaLabel={intl.formatMessage(intlMessages.enableAutoarrangeLayoutLabel)}
/>
<p>{`${intl.formatMessage(intlMessages.enableAutoarrangeLayoutDescription)}`}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</Resizable>
</Draggable>
);
}
}
export default withLayoutConsumer(injectIntl(DebugWindow));

View File

@ -0,0 +1,96 @@
.debugWindowWrapper {
position: absolute !important;
z-index: 9;
}
.debugWindow {
min-width: 20vw;
min-height: 20vh;
width: 100%;
height: 100%;
background-color: white;
border: 2px solid #06172A;
&::after {
content: "";
-webkit-transform: rotate(-45deg);
position: absolute;
right: 2px;
bottom: 8px;
pointer-events: none;
width: 14px;
height: 1px;
background: rgba(0,0,0,.5);
}
&::before {
content: "";
-webkit-transform: rotate(-45deg);
position: absolute;
right: 2px;
bottom: 5px;
pointer-events: none;
width: 8px;
height: 1px;
background: rgba(0,0,0,.5);
}
.header {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid lightgray;
cursor: move;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
.title {
font-size: 1.2rem;
font-weight: bold;
}
.moveIcon {
margin: 5px;
color: rgba(0,0,0,.5);
}
.close {
span {
i {
font-size: 115%;
}
}
}
}
.debugWindowContent {
padding: 10px;
.table{
display: table;
width: 100%;
.row{
display: table-row;
}
.cell {
display: table-cell;
padding: 5px;
vertical-align: middle;
.cellContent {
display: flex;
align-items: center;
}
}
}
.userAgentInput, .autoArrangeToggle {
margin-right: 5px;
}
}
}

View File

@ -168,13 +168,22 @@ class PresentationArea extends PureComponent {
this.onResize(); this.onResize();
} }
if (prevProps.slidePosition.id !== slidePosition.id) {
window.dispatchEvent(new Event('slideChanged'));
}
const { width: prevWidth, height: prevHeight } = prevProps.slidePosition; const { width: prevWidth, height: prevHeight } = prevProps.slidePosition;
const { width: currWidth, height: currHeight } = slidePosition; const { width: currWidth, height: currHeight } = slidePosition;
if (prevProps.slidePosition.id !== slidePosition.id) {
if ((prevWidth > prevHeight && currHeight > currWidth)
|| (prevHeight > prevWidth && currWidth > currHeight)) {
layoutContextDispatch(
{
type: 'setAutoArrangeLayout',
value: true,
},
);
}
window.dispatchEvent(new Event('slideChanged'));
}
if (prevWidth !== currWidth || prevHeight !== currHeight) { if (prevWidth !== currWidth || prevHeight !== currHeight) {
layoutContextDispatch({ layoutContextDispatch({
type: 'setPresentationSlideSize', type: 'setPresentationSlideSize',

View File

@ -38,6 +38,7 @@ public:
duration: 4000 duration: 4000
remainingTimeThreshold: 30 remainingTimeThreshold: 30
remainingTimeAlertThreshold: 1 remainingTimeAlertThreshold: 1
enableDebugWindow: true
# Warning: increasing the limit of breakout rooms per meeting # Warning: increasing the limit of breakout rooms per meeting
# can generate excessive overhead to the server. We recommend # can generate excessive overhead to the server. We recommend
# this value to be kept under 12. # this value to be kept under 12.
@ -88,6 +89,9 @@ public:
openActions: openActions:
accesskey: A accesskey: A
descId: openActions descId: openActions
openDebugWindow:
accesskey: K
descId: openDebugWindow
branding: branding:
displayBrandingArea: true displayBrandingArea: true
connectionTimeout: 60000 connectionTimeout: 60000

View File

@ -720,5 +720,10 @@
"app.iOSWarning.label": "Please upgrade to iOS 12.2 or higher", "app.iOSWarning.label": "Please upgrade to iOS 12.2 or higher",
"app.legacy.unsupportedBrowser": "It looks like you're using a browser that is not supported. Please use either {0} or {1} for full support.", "app.legacy.unsupportedBrowser": "It looks like you're using a browser that is not supported. Please use either {0} or {1} for full support.",
"app.legacy.upgradeBrowser": "It looks like you're using an older version of a supported browser. Please upgrade your browser for full support.", "app.legacy.upgradeBrowser": "It looks like you're using an older version of a supported browser. Please upgrade your browser for full support.",
"app.legacy.criosBrowser": "On iOS please use Safari for full support." "app.legacy.criosBrowser": "On iOS please use Safari for full support.",
"app.debugWindow.windowTitle": "Debug",
"app.debugWindow.form.userAgentLabel": "User Agent",
"app.debugWindow.form.button.copy": "Copy",
"app.debugWindow.form.enableAutoarrangeLayoutLabel": "Enable Auto Arrange Layout",
"app.debugWindow.form.enableAutoarrangeLayoutDescription": "(it will be disabled if you drag or resize the webcams area)"
} }