diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx
index d87edbf71a..4ea3354d0c 100755
--- a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx
@@ -249,6 +249,7 @@ class ActionsDropdown extends PureComponent {
presentations,
setPresentation,
podIds,
+ setPresentationFitToWidth,
} = this.props;
if (!podIds || podIds.length < 1) return [];
@@ -272,6 +273,7 @@ class ActionsDropdown extends PureComponent {
description: "uploaded presentation file",
key: `uploaded-presentation-${p.id}`,
onClick: () => {
+ setPresentationFitToWidth(false);
setPresentation(p.id, podId);
},
}
diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx
index d0e1d262ff..d1b9b216e1 100755
--- a/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx
@@ -39,6 +39,7 @@ class ActionsBar extends PureComponent {
setMeetingLayout,
showPushLayout,
setPushLayout,
+ setPresentationFitToWidth,
} = this.props;
const shouldShowOptionsButton = (isPresentationEnabled() && isThereCurrentPresentation)
@@ -67,6 +68,7 @@ class ActionsBar extends PureComponent {
setPushLayout,
presentationIsOpen,
showPushLayout,
+ setPresentationFitToWidth,
}}
/>
{isCaptionsAvailable
diff --git a/bigbluebutton-html5/imports/ui/components/app/component.jsx b/bigbluebutton-html5/imports/ui/components/app/component.jsx
index 5a62095241..572465eb82 100644
--- a/bigbluebutton-html5/imports/ui/components/app/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/app/component.jsx
@@ -131,8 +131,10 @@ class App extends Component {
super(props);
this.state = {
enableResize: !window.matchMedia(MOBILE_MEDIA).matches,
+ presentationFitToWidth: false,
};
+ this.setPresentationFitToWidth = this.setPresentationFitToWidth.bind(this);
this.handleWindowResize = throttle(this.handleWindowResize).bind(this);
this.shouldAriaHide = this.shouldAriaHide.bind(this);
@@ -283,6 +285,10 @@ class App extends Component {
ConnectionStatusService.stopRoundTripTime();
}
+ setPresentationFitToWidth(presentationFitToWidth) {
+ this.setState({ presentationFitToWidth });
+ }
+
handleWindowResize() {
const { enableResize } = this.state;
const shouldEnableResize = !window.matchMedia(MOBILE_MEDIA).matches;
@@ -403,6 +409,7 @@ class App extends Component {
setMeetingLayout={setMeetingLayout}
showPushLayout={showPushLayoutButton && selectedLayout === 'custom'}
presentationIsOpen={presentationIsOpen}
+ setPresentationFitToWidth={this.setPresentationFitToWidth}
/>
);
@@ -517,6 +524,8 @@ class App extends Component {
darkTheme,
} = this.props;
+ const { presentationFitToWidth } = this.state;
+
return (
<>
@@ -540,7 +549,7 @@ class App extends Component {
- {shouldShowPresentation ? : null}
+ {shouldShowPresentation ? : null}
{shouldShowScreenshare ? : null}
{
shouldShowExternalVideo
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
index bf46dca8d1..1e58599077 100755
--- a/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
@@ -74,7 +74,6 @@ class Presentation extends PureComponent {
presentationWidth: 0,
presentationHeight: 0,
zoom: 100,
- fitToWidth: false,
isFullscreen: false,
tldrawAPI: null,
isPanning: false,
@@ -86,7 +85,6 @@ class Presentation extends PureComponent {
this.currentPresentationToastId = null;
this.getSvgRef = this.getSvgRef.bind(this);
- this.setFitToWidth = this.setFitToWidth.bind(this);
this.zoomChanger = debounce({ delay: 200 }, this.zoomChanger.bind(this));
this.updateLocalPosition = this.updateLocalPosition.bind(this);
this.panAndZoomChanger = this.panAndZoomChanger.bind(this);
@@ -207,13 +205,13 @@ class Presentation extends PureComponent {
multiUser,
numPages,
currentPresentationId,
+ fitToWidth,
} = this.props;
const {
presentationWidth,
presentationHeight,
zoom,
isPanning,
- fitToWidth,
presentationId,
hadPresentation,
} = this.state;
@@ -505,19 +503,14 @@ class Presentation extends PureComponent {
}
}
- setFitToWidth(fitToWidth) {
- this.setState({ fitToWidth });
- }
-
zoomChanger(zoom) {
this.setState({ zoom });
}
fitToWidthHandler() {
- const { fitToWidth } = this.state;
-
+ const { setPresentationFitToWidth, fitToWidth } = this.props;
+ setPresentationFitToWidth(!fitToWidth)
this.setState({
- fitToWidth: !fitToWidth,
zoom: HUNDRED_PERCENT,
});
}
@@ -535,9 +528,9 @@ class Presentation extends PureComponent {
}
calculateSize(viewBoxDimensions) {
- const { presentationHeight, presentationWidth, fitToWidth } = this.state;
+ const { presentationHeight, presentationWidth } = this.state;
- const { userIsPresenter, currentSlide, slidePosition } = this.props;
+ const { userIsPresenter, currentSlide, slidePosition, fitToWidth } = this.props;
if (!currentSlide || !slidePosition) {
return { width: 0, height: 0 };
@@ -605,8 +598,9 @@ class Presentation extends PureComponent {
removeWhiteboardGlobalAccess,
multiUserSize,
multiUser,
+ fitToWidth,
} = this.props;
- const { zoom, fitToWidth, isPanning } = this.state;
+ const { zoom, isPanning } = this.state;
if (!currentSlide) return null;
@@ -733,12 +727,12 @@ class Presentation extends PureComponent {
layoutContextDispatch,
presentationIsOpen,
darkTheme,
+ fitToWidth,
} = this.props;
const {
isFullscreen,
localPosition,
- fitToWidth,
zoom,
tldrawIsMounting,
isPanning,
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-area/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-area/component.jsx
index cd351d329f..43e4e0a515 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-area/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-area/component.jsx
@@ -7,13 +7,15 @@ const PresentationArea = ({
height,
presentationIsOpen,
darkTheme,
+ setPresentationFitToWidth,
+ fitToWidth,
}) => {
const presentationAreaSize = {
presentationAreaWidth: width,
presentationAreaHeight: height,
};
return (
-
+
);
};
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-area/container.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-area/container.jsx
index fc76dfad02..8b8a66004d 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-area/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-area/container.jsx
@@ -3,10 +3,10 @@ import PropTypes from 'prop-types';
import { layoutSelectOutput } from '../../layout/context';
import PresentationArea from './component';
-const PresentationAreaContainer = ({ presentationIsOpen, darkTheme }) => {
+const PresentationAreaContainer = ({ presentationIsOpen, darkTheme, setPresentationFitToWidth, fitToWidth }) => {
const presentation = layoutSelectOutput((i) => i.presentation);
- return ;
+ return ;
};
export default PresentationAreaContainer;
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx
index 8321daa07c..1a30a59523 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx
@@ -104,7 +104,6 @@ export default function Whiteboard(props) {
const language = mapLanguage(Settings?.application?.locale?.toLowerCase() || 'en');
const [currentTool, setCurrentTool] = React.useState(null);
const [currentStyle, setCurrentStyle] = React.useState({});
- const [currentCameraPoint, setCurrentCameraPoint] = React.useState({});
const [isMoving, setIsMoving] = React.useState(false);
const [isPanning, setIsPanning] = React.useState(shortcutPanning);
const [panSelected, setPanSelected] = React.useState(isPanning);
@@ -472,16 +471,12 @@ export default function Whiteboard(props) {
}
}, [tldrawAPI?.getPageState()?.camera, presentationWidth, presentationHeight]);
- // change tldraw page when presentation page changes
React.useEffect(() => {
- if (tldrawAPI && curPageId && slidePosition) {
- tldrawAPI.changePage(curPageId);
- const newZoom = prevSlidePosition
- ? calculateZoom(prevSlidePosition.viewBoxWidth, prevSlidePosition.viewBoxHeight)
- : calculateZoom(slidePosition.viewBoxWidth, slidePosition.viewBoxHeight);
- tldrawAPI?.setCamera([slidePosition.x, slidePosition.y], newZoom, 'zoomed_previous_page');
+ if (isPresenter && slidePosition) {
+ const currentZoom = calculateZoom(slidePosition?.viewBoxWidth, slidePosition?.viewBoxHeight);
+ tldrawAPI?.setCamera([slidePosition?.x, slidePosition?.y], currentZoom);
}
- }, [curPageId]);
+ }, [slidePosition?.viewBoxWidth, slidePosition?.viewBoxHeight]);
// change tldraw camera when slidePosition changes
React.useEffect(() => {
@@ -812,10 +807,6 @@ export default function Whiteboard(props) {
if (reason && isPresenter && slidePosition && (reason.includes('zoomed') || reason.includes('panned'))) {
const camera = tldrawAPI?.getPageState()?.camera;
- const isForcePanning = tldrawAPI?.isForcePanning;
- if (currentCameraPoint[curPageId] && !isPanning && !isForcePanning) {
- camera.point = currentCameraPoint[curPageId];
- }
// limit bounds
if (tldrawAPI?.viewport.maxX > slidePosition.width) {
@@ -831,6 +822,11 @@ export default function Whiteboard(props) {
camera.point[1] = 0;
}
+ if (camera.point[0] === 0 && camera.point[1] === 0) {
+ const newZoom = calculateZoom(slidePosition.viewBoxWidth, slidePosition.viewBoxHeight);
+ e?.setCamera([slidePosition.x, slidePosition.y], newZoom);
+ }
+
const zoomFitSlide = calculateZoom(slidePosition.width, slidePosition.height);
if (camera.zoom < zoomFitSlide) {
camera.zoom = zoomFitSlide;
@@ -854,20 +850,13 @@ export default function Whiteboard(props) {
viewedRegionH = HUNDRED_PERCENT;
}
- if (e?.currentPageId == curPageId) {
- setCurrentCameraPoint({
- ...currentCameraPoint,
- [e?.currentPageId]: camera?.point,
- })
- }
-
zoomSlide(
parseInt(curPageId, 10),
podId,
viewedRegionW,
viewedRegionH,
- currentCameraPoint[curPageId] ? currentCameraPoint[curPageId][0] : camera.point[0],
- currentCameraPoint[curPageId] ? currentCameraPoint[curPageId][1] : camera.point[1],
+ camera.point[0],
+ camera.point[1],
);
}
// don't allow non-presenters to pan&zoom
@@ -1006,16 +995,6 @@ export default function Whiteboard(props) {
setCurrentStyle({ ...currentStyle, ...command?.after?.appState?.currentStyle });
}
- if (command && command?.id?.includes('change_page')) {
- const camera = tldrawAPI?.getPageState()?.camera;
- if (currentCameraPoint[app?.currentPageId] && camera) {
- tldrawAPI?.setCamera(
- [currentCameraPoint[app?.currentPageId][0], currentCameraPoint[app?.currentPageId][1]],
- camera?.zoom
- );
- }
- }
-
const changedShapes = command.after?.document?.pages[app.currentPageId]?.shapes;
if (!isMounting && app.currentPageId !== curPageId) {
// can happen then the "move to page action" is called, or using undo after changing a page
diff --git a/bigbluebutton-tests/playwright/presentation/presentation.spec.js b/bigbluebutton-tests/playwright/presentation/presentation.spec.js
index 9e9c633cef..b10241e464 100644
--- a/bigbluebutton-tests/playwright/presentation/presentation.spec.js
+++ b/bigbluebutton-tests/playwright/presentation/presentation.spec.js
@@ -52,11 +52,7 @@ test.describe.parallel('Presentation', () => {
await presentation.hidePresentationToolbar();
});
- /**
- * temporally skipped because it's currently failing the screenshot comparisons
- * due to https://github.com/bigbluebutton/bigbluebutton/issues/18232
- */
- test.skip('Zoom In, Zoom Out, Reset Zoom @ci', async ({ browser, context, page }) => {
+ test('Zoom In, Zoom Out, Reset Zoom @ci', async ({ browser, context, page }) => {
const presentation = new Presentation(browser, context);
await presentation.initPages(page);
await presentation.zoom();