Merge pull request #14184 from KDSBrowne/BBB-14141

Add Polite Presentation Slide Change Announcement (Screen Reader)
This commit is contained in:
Anton Georgiev 2022-01-24 09:14:13 -05:00 committed by GitHub
commit 7a733b7382
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 6 deletions

View File

@ -127,7 +127,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<!-- fonts -->
</head>
<body style="background-color: #06172A">
<div id="app" role="document"></div>
<div id="aria-polite-alert" aria-live="polite" aria-atomic="false" class="sr-only"></div>
<div id="app" role="document">
</div>
<span id="destination"></span>
<audio id="remote-media" autoplay>
</audio>

View File

@ -16,7 +16,7 @@ import SettingsDropdownContainer from './settings-dropdown/container';
import browserInfo from '/imports/utils/browserInfo';
import deviceInfo from '/imports/utils/deviceInfo';
import _ from "lodash";
import {alertScreenReader} from '/imports/utils/dom-utils';
import { politeSRAlert } from '/imports/utils/dom-utils';
import { PANELS, ACTIONS } from '../layout/enums';
const intlMessages = defineMessages({
@ -193,7 +193,7 @@ class NavBar extends Component {
activeChats.map((c, i) => {
if (c?.unreadCounter > 0 && c?.unreadCounter !== acs[i]?.unreadCounter) {
alertScreenReader(`${intl.formatMessage(intlMessages.newMsgAria, { 0: c.name })}`)
politeSRAlert(`${intl.formatMessage(intlMessages.newMsgAria, { 0: c.name })}`)
}
});

View File

@ -5,6 +5,7 @@ import WhiteboardToolbarContainer from '/imports/ui/components/whiteboard/whiteb
import { HUNDRED_PERCENT, MAX_PERCENT } from '/imports/utils/slideCalcUtils';
import { defineMessages, injectIntl } from 'react-intl';
import { toast } from 'react-toastify';
import { politeSRAlert } from '/imports/utils/dom-utils';
import PresentationToolbarContainer from './presentation-toolbar/container';
import PresentationPlaceholder from './presentation-placeholder/component';
import CursorWrapperContainer from './cursor/cursor-wrapper-container/container';
@ -45,6 +46,10 @@ const intlMessages = defineMessages({
id: 'app.presentation.endSlideContent',
description: 'Indicate the slide content end',
},
slideContentChanged: {
id: 'app.presentation.changedSlideContent',
description: 'Indicate the slide content has changed',
},
noSlideContent: {
id: 'app.presentation.emptySlideContent',
description: 'No content available for slide',
@ -112,7 +117,8 @@ class Presentation extends PureComponent {
componentDidMount() {
this.getInitialPresentationSizes();
this.refPresentationContainer.addEventListener(FULLSCREEN_CHANGE_EVENT, this.onFullscreenChange);
this.refPresentationContainer
.addEventListener(FULLSCREEN_CHANGE_EVENT, this.onFullscreenChange);
window.addEventListener('resize', this.onResize, false);
const {
@ -148,6 +154,7 @@ class Presentation extends PureComponent {
userIsPresenter,
presentationBounds,
numCameras,
intl,
} = this.props;
const {
@ -159,6 +166,10 @@ class Presentation extends PureComponent {
this.onResize();
}
if (currentSlide.num !== prevProps.currentSlide.num) {
politeSRAlert(intl.formatMessage(intlMessages.slideContentChanged, { 0: currentSlide.num }));
}
if (prevProps?.slidePosition && slidePosition) {
const { width: prevWidth, height: prevHeight } = prevProps.slidePosition;
const { width: currWidth, height: currHeight } = slidePosition;
@ -225,7 +236,8 @@ class Presentation extends PureComponent {
const { fullscreenContext, layoutContextDispatch } = this.props;
window.removeEventListener('resize', this.onResize, false);
this.refPresentationContainer.removeEventListener(FULLSCREEN_CHANGE_EVENT, this.onFullscreenChange);
this.refPresentationContainer
.removeEventListener(FULLSCREEN_CHANGE_EVENT, this.onFullscreenChange);
if (fullscreenContext) {
layoutContextDispatch({

View File

@ -1,6 +1,7 @@
const TITLE_WITH_VIEW = 3;
const ARIA_ALERT_TIMEOUT = 3000;
const ARIA_ALERT_EXT_TIMEOUT = 15000;
const getTitleData = () => {
const title = document.getElementsByTagName('title')[0];
@ -37,4 +38,12 @@ export const alertScreenReader = (s = '') => {
}, ARIA_ALERT_TIMEOUT);
};
export default { registerTitleView, unregisterTitleView, alertScreenReader };
export const politeSRAlert = (s = '') => {
const liveArea = document.getElementById('aria-polite-alert')
if (liveArea) liveArea.innerHTML = s;
setTimeout(() => {
if (liveArea) liveArea.innerHTML = '';
}, ARIA_ALERT_EXT_TIMEOUT);
};
export default { registerTitleView, unregisterTitleView, alertScreenReader, politeSRAlert };

View File

@ -164,6 +164,7 @@
"app.presentation.slideContent": "Slide Content",
"app.presentation.startSlideContent": "Slide content start",
"app.presentation.endSlideContent": "Slide content end",
"app.presentation.changedSlideContent": "Presentation changed to slide: {0}",
"app.presentation.emptySlideContent": "No content for current slide",
"app.presentation.presentationToolbar.noNextSlideDesc": "End of presentation",
"app.presentation.presentationToolbar.noPrevSlideDesc": "Start of presentation",