Merge pull request #16801 from KDSBrowne/bbb-16662

refactor: Move Pan Tool Next To The Pointer Tool
This commit is contained in:
Ramón Souza 2023-02-27 16:28:21 -03:00 committed by GitHub
commit aa517df377
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 252 additions and 22 deletions

View File

@ -98,6 +98,16 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
main {
display: initial;
}
.overrideSelect {
background-color: #FFF !important;
color: #000 !important;
}
.select {
background-color: rgba(66, 133, 244, 1) !important;
color: #FFF !important;
}
</style>
<script>
document.addEventListener('gesturestart', function (e) {

View File

@ -264,9 +264,7 @@ class PresentationToolbar extends PureComponent {
currentSlide,
slidePosition,
multiUserSize,
multiUser,
setIsPanning,
isPanning,
multiUser
} = this.props;
const { isMobile } = deviceInfo;
@ -400,20 +398,6 @@ class PresentationToolbar extends PureComponent {
/>
</TooltipContainer>
) : null}
<Styled.FitToWidthButton
role="button"
data-test="panButton"
aria-label={intl.formatMessage(intlMessages.pan)}
color="light"
disabled={(zoom <= HUNDRED_PERCENT && !fitToWidth)}
icon="hand"
size="md"
circle
onClick={setIsPanning}
label={intl.formatMessage(intlMessages.pan)}
hideLabel
panning={isPanning}
/>
<Styled.FitToWidthButton
role="button"
data-test="fitToWidthButton"

View File

@ -10,6 +10,8 @@ import logger from '/imports/startup/client/logger';
import KEY_CODES from '/imports/utils/keyCodes';
import { presentationMenuHeight, borderSize, borderSizeLarge } from '/imports/ui/stylesheets/styled-components/general';
import { colorWhite, colorBlack } from '/imports/ui/stylesheets/styled-components/palette';
import Styled from './styles';
import PanToolInjector from './pan-tool-injector/component';
function usePrevious(value) {
const ref = React.useRef();
@ -49,6 +51,7 @@ const SMALLEST_WIDTH = 645;
const TOOLBAR_SMALL = 28;
const TOOLBAR_LARGE = 38;
const TOOLBAR_OFFSET = 0;
const DEFAULT_TOOL_COUNT = 9;
const TldrawGlobalStyle = createGlobalStyle`
${({ hideContextMenu }) => hideContextMenu && `
@ -149,7 +152,6 @@ export default function Whiteboard(props) {
isRTL,
fitToWidth,
zoomValue,
isPanning,
intl,
svgUri,
maxStickyNoteLength,
@ -160,8 +162,8 @@ export default function Whiteboard(props) {
maxNumberOfAnnotations,
notifyShapeNumberExceeded,
darkTheme,
isPanning: shortcutPanning,
} = props;
const { pages, pageStates } = initDefaultPages(curPres?.pages.length || 1);
const rDocument = React.useRef({
name: "test",
@ -186,6 +188,60 @@ export default function Whiteboard(props) {
const language = mapLanguage(Settings?.application?.locale?.toLowerCase() || 'en');
const [currentTool, setCurrentTool] = React.useState(null);
const [isMoving, setIsMoving] = React.useState(false);
const [isPanning, setIsPanning] = React.useState(shortcutPanning);
const [panSelected, setPanSelected] = React.useState(isPanning);
const isMountedRef = React.useRef(true);
React.useEffect(() => {
return () => {
isMountedRef.current = false;
};
}, []);
const setSafeTLDrawAPI = (api) => {
if (isMountedRef.current) {
setTLDrawAPI(api);
}
};
const setSafeCurrentTool = (tool) => {
if (isMountedRef.current) {
setCurrentTool(tool);
}
};
const toggleOffCheck = (evt) => {
const clickedElement = evt.target;
const toolbar = document.getElementById("TD-PrimaryTools");
const panBtnClicked = clickedElement?.getAttribute('data-test') === 'panButton'
|| clickedElement?.parentElement?.getAttribute('data-test') === 'panButton';
const panButton = document.querySelector('[data-test="panButton"]');
if (panBtnClicked) {
const dataZoom = panButton.getAttribute('data-zoom');
if ((dataZoom <= HUNDRED_PERCENT && !fitToWidth)) {
return;
}
panButton.classList.add('select');
panButton.classList.remove('selectOverride');
return;
} else {
setIsPanning(false);
setPanSelected(false);
panButton.classList.add('selectOverride');
panButton.classList.remove('select');
}
};
React.useEffect(() => {
const toolbar = document.getElementById("TD-PrimaryTools");
const handleClick = (evt) => {
toggleOffCheck(evt);
};
toolbar?.addEventListener('click', handleClick);
return () => {
toolbar?.removeEventListener('click', handleClick);
};
}, [tldrawAPI]);
const throttledResetCurrentPoint = React.useRef(_.throttle(() => {
setEnable(false);
@ -676,6 +732,8 @@ export default function Whiteboard(props) {
const onMount = (app) => {
const menu = document.getElementById("TD-Styles")?.parentElement;
setSafeCurrentTool('select');
if (menu) {
const MENU_OFFSET = `48px`;
menu.style.position = `relative`;
@ -703,7 +761,7 @@ export default function Whiteboard(props) {
}
);
setTLDrawAPI(app);
setSafeTLDrawAPI(app);
props.setTldrawAPI(app);
// disable for non presenter that doesn't have multi user access
if (!hasWBAccess && !isPresenter) {
@ -771,7 +829,7 @@ export default function Whiteboard(props) {
}
if (reason && isPresenter && slidePosition && (reason.includes("zoomed") || reason.includes("panned"))) {
const camera = tldrawAPI.getPageState()?.camera;
const camera = tldrawAPI?.getPageState()?.camera;
// limit bounds
if (tldrawAPI?.viewport.maxX > slidePosition.width) {
@ -862,8 +920,9 @@ export default function Whiteboard(props) {
if (reason && reason.includes('selected_tool')) {
const tool = reason.split(':')[1];
setCurrentTool(tool);
setPanSelected(false);
setIsPanning(false);
}
};
@ -1021,6 +1080,21 @@ export default function Whiteboard(props) {
}}
/>
</Cursors>
{isPresenter &&
<PanToolInjector
{...{
tldrawAPI,
fitToWidth,
isPanning,
setIsPanning,
zoomValue,
panSelected,
setPanSelected,
currentTool,
}}
formatMessage={intl?.formatMessage}
/>
}
</>
);
}

View File

@ -0,0 +1,124 @@
import * as React from "react";
import ReactDOM from 'react-dom';
import { HUNDRED_PERCENT } from '/imports/utils/slideCalcUtils';
import Styled from '../styles';
const DEFAULT_TOOL_COUNT = 9;
class PanToolInjector extends React.Component {
componentDidMount() {
this.addPanTool();
}
componentDidUpdate(prevProps) {
const {
zoomValue,
fitToWidth,
isPanning,
setIsPanning,
formatMessage,
tldrawAPI,
panSelected,
setPanSelected
} = this.props;
if (prevProps.zoomValue !== zoomValue
|| prevProps.fitToWidth !== fitToWidth
|| prevProps.isPanning !== isPanning
|| prevProps.tldrawAPI !== tldrawAPI
|| prevProps.panSelected !== panSelected
) {
this.addPanTool();
if (panSelected) {
// tldrawAPI?.selectTool('draw');
setIsPanning(true);
setPanSelected(true);
} else {
setIsPanning(false);
setPanSelected(false);
}
}
}
addPanTool() {
const {
zoomValue,
fitToWidth,
isPanning,
setIsPanning,
formatMessage,
tldrawAPI,
panSelected,
setPanSelected
} = this.props;
const tools = document.querySelectorAll('[id*="TD-PrimaryTools-"]');
tools.forEach(tool => {
const classList = tool.firstElementChild.classList;
if (panSelected) {
classList.add('overrideSelect');
tldrawAPI?.selectTool('draw');
} else {
classList.remove('overrideSelect');
}
});
if (zoomValue === HUNDRED_PERCENT) {
setPanSelected(false);
setIsPanning(false);
tldrawAPI?.selectTool('select');
}
const parentElement = document.getElementById('TD-PrimaryTools');
if (!parentElement) return;
if (parentElement.childElementCount === DEFAULT_TOOL_COUNT) {
parentElement.removeChild(parentElement.children[1]);
}
if (parentElement.childElementCount < DEFAULT_TOOL_COUNT) {
const label = formatMessage({
id: 'app.whiteboard.toolbar.tools.hand',
description: 'presentation toolbar pan label',
});
const container = document.createElement('span');
parentElement.appendChild(container);
ReactDOM.render(
<Styled.PanTool
key={'bbb-panBtn'}
role="button"
data-test="panButton"
data-zoom={zoomValue}
className={"overrideSelect"}
color="light"
icon="hand"
size="md"
aria-label={label}
disabled={(zoomValue <= HUNDRED_PERCENT && !fitToWidth)}
onClick={() => {
setPanSelected(true);
setIsPanning(true);
if (!(zoomValue <= HUNDRED_PERCENT && !fitToWidth)) {
const panButton = document.querySelector('[data-test="panButton"]');
if (panButton) {
panButton.classList.remove('selectOverride');
panButton.classList.add('select');
}
}
}}
label={label}
hideLabel
/>,
container
);
const lastChild = parentElement.lastChild;
const secondChild = parentElement.children[1];
parentElement.insertBefore(lastChild, secondChild);
}
}
render() {
return null;
}
}
export default PanToolInjector;

View File

@ -0,0 +1,38 @@
import styled from 'styled-components';
import {
toolbarButtonColor,
colorWhite,
} from '/imports/ui/stylesheets/styled-components/palette';
import {
fontSizeLarger,
} from '/imports/ui/stylesheets/styled-components/typography';
import Button from '/imports/ui/components/common/button/component';
const PanTool = styled(Button)`
border: none !important;
padding: 0;
margin: 0;
border-radius: 7px;
background-color: ${colorWhite};
color: ${toolbarButtonColor};
& > i {
font-size: ${fontSizeLarger} !important;
[dir="rtl"] & {
-webkit-transform: scale(-1, 1);
-moz-transform: scale(-1, 1);
-ms-transform: scale(-1, 1);
-o-transform: scale(-1, 1);
transform: scale(-1, 1);
}
}
&:hover,
&:focus {
background-color: var(--colors-hover);
}
`;
export default {
PanTool,
};