Skip to content

Commit

Permalink
fix microsoft#2193: Attachments not spoken by Narrator
Browse files Browse the repository at this point in the history
  • Loading branch information
corinagum committed Jul 24, 2019
1 parent 02f772d commit b6298eb
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 35 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

- Fix [#2160](https://github.com/microsoft/BotFramework-WebChat/issues/2160). Clear suggested actions after clicking on a suggested actions of type `openUrl`, by [@tdurnford](https://github.com/tdurnford) in PR [#2190](https://github.com/microsoft/BotFramework-WebChat/pull/2190)
- Fix [#2187](https://github.com/microsoft/BotFramework-WebChat/issues/2187). Bump core-js and update core-js modules on index-es5.js, by [@corinagum](https://github.com/corinagum) in PR [#2195](https://github.com/microsoft/BotFramework-WebChat/pull/2195)
- Fix [#2193](https://github.com/microsoft/BotFramework-WebChat/issues/2193). Fix Adaptive Card/attachments do not get read by Narrator, by [@corinagum](https://github.com/corinagum) in PR [#XXX](https://github.com/microsoft/BotFramework-WebChat/pull/XXX)


## [4.5.0] - 2019-07-10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ class AdaptiveCardRenderer extends React.PureComponent {
<pre>{JSON.stringify(error, null, 2)}</pre>
</ErrorBox>
) : (
<div className={styleSet.adaptiveCardRenderer} onClick={this.handleClick} ref={this.contentRef} />
<div aria-label=" " className={styleSet.adaptiveCardRenderer} onClick={this.handleClick} ref={this.contentRef} />
);
}
}
Expand Down
5 changes: 2 additions & 3 deletions packages/component/src/Activity/Bubble.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,20 @@ import React from 'react';

import connectToWebChat from '../connectToWebChat';

const Bubble = ({ 'aria-hidden': ariaHidden, children, className, fromUser, styleSet }) => (
const Bubble = ({ ariaHidden, children, className, fromUser, styleSet }) => (
<div aria-hidden={ariaHidden} className={classNames(styleSet.bubble + '', { 'from-user': fromUser }, className + '')}>
{children}
</div>
);

Bubble.defaultProps = {
'aria-hidden': true,
children: undefined,
className: '',
fromUser: false
};

Bubble.propTypes = {
'aria-hidden': PropTypes.bool,
ariaHidden: PropTypes.bool.isRequired,
children: PropTypes.any,
className: PropTypes.string,
fromUser: PropTypes.bool,
Expand Down
12 changes: 7 additions & 5 deletions packages/component/src/Activity/StackedLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,9 @@ const StackedLayout = ({ activity, avatarInitials, children, language, styleSet,
</div>
) : (
!!activityDisplayText && (
<div aria-label={ariaLabel} className="webchat__row message">
<Bubble aria-hidden={true} className="bubble" fromUser={fromUser}>
<div className="webchat__row message">
<span aria-label={ariaLabel} />
<Bubble ariaHidden={true} className="bubble" fromUser={fromUser}>
{children({
activity,
attachment: {
Expand All @@ -133,8 +134,9 @@ const StackedLayout = ({ activity, avatarInitials, children, language, styleSet,
)
)}
{attachments.map((attachment, index) => (
<div className="webchat__row attachment" key={index}>
<Bubble aria-hidden={true} className="attachment bubble" fromUser={fromUser} key={index}>
<div aria-label=" " className="webchat__row attachment" key={index}>
<span aria-label={fromUser ? localize('UserSent', language) : localize('BotSent', language)} />
<Bubble ariaHidden={false} className="attachment bubble" fromUser={fromUser} key={index}>
{children({ attachment })}
</Bubble>
</div>
Expand All @@ -143,7 +145,7 @@ const StackedLayout = ({ activity, avatarInitials, children, language, styleSet,
{showSendStatus ? (
<SendStatus activity={activity} className="timestamp" />
) : (
<Timestamp activity={activity} aria-hidden={true} className={classNames('timestamp', timestampClassName)} />
<Timestamp activity={activity} className={classNames('timestamp', timestampClassName)} />
)}
<div className="filler" />
</div>
Expand Down
6 changes: 2 additions & 4 deletions packages/component/src/Attachment/Assets/DownloadIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import React from 'react';

const ICON_SIZE_FACTOR = 22;

const DownloadIcon = ({ className, label, size }) => (
const DownloadIcon = ({ className, size }) => (
<svg
aria-label={label}
aria-hidden={true}
className={className}
height={ICON_SIZE_FACTOR * size}
viewBox="0 0 31.8 46"
Expand All @@ -17,13 +17,11 @@ const DownloadIcon = ({ className, label, size }) => (

DownloadIcon.defaultProps = {
className: '',
label: '',
size: 1
};

DownloadIcon.propTypes = {
className: PropTypes.string,
label: PropTypes.string,
size: PropTypes.number
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';

import connectToWebChat from '../../connectToWebChat';

const TypingAnimation = ({ styleSet }) => <div className={styleSet.typingAnimation} />;
const TypingAnimation = ({ styleSet }) => <div aria-label="typing indicator" className={styleSet.typingAnimation} />;

TypingAnimation.propTypes = {
styleSet: PropTypes.shape({
Expand Down
14 changes: 12 additions & 2 deletions packages/component/src/Attachment/AudioContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,27 @@ import React from 'react';

import connectToWebChat from '../connectToWebChat';

const AudioContent = ({ autoPlay, loop, poster, src, styleSet }) => (
<audio autoPlay={autoPlay} className={styleSet.audioContent} controls={true} loop={loop} poster={poster} src={src} />
const AudioContent = ({ alt, autoPlay, loop, poster, src, styleSet }) => (
<audio
aria-label={alt}
autoPlay={autoPlay}
className={styleSet.audioContent}
controls={true}
loop={loop}
poster={poster}
src={src}
/>
);

AudioContent.defaultProps = {
alt: '',
autoPlay: false,
loop: false,
poster: ''
};

AudioContent.propTypes = {
alt: PropTypes.string,
autoPlay: PropTypes.bool,
loop: PropTypes.bool,
poster: PropTypes.string,
Expand Down
19 changes: 13 additions & 6 deletions packages/component/src/Attachment/DownloadAttachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,24 @@ const DownloadAttachment = ({
styleSet
}) => {
const attachmentIndex = attachments.indexOf(attachment);
const label = localize('Download file', language);
const downloadLabel = localize('Download file', language);
const size = attachmentSizes[attachmentIndex];

const formattedSize = typeof size === 'number' && format(size);
const downloadFileWithFileSizeLabel = localize(
'DownloadFileWithFileSize',
language,
downloadLabel,
attachment.name,
formattedSize
);
return (
<div className={styleSet.downloadAttachment}>
<a href={attachment.contentUrl} rel="noopener noreferrer" target="_blank">
<div aria-label={downloadFileWithFileSizeLabel} className={styleSet.downloadAttachment}>
<a aria-hidden={true} href={attachment.contentUrl} rel="noopener noreferrer" target="_blank">
<div className="details">
<div className="name">{attachment.name}</div>
{typeof size === 'number' && <div className="size">{format(size)}</div>}
<div className="size">{formattedSize}</div>
</div>
<DownloadIcon className="icon" label={label} size={1.5} />
<DownloadIcon className="icon" size={1.5} />
</a>
</div>
);
Expand Down
23 changes: 16 additions & 7 deletions packages/component/src/Attachment/TextContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,24 @@ import connectToWebChat from '../connectToWebChat';

const TextContent = ({ contentType, renderMarkdown, styleSet, text }) =>
contentType === 'text/markdown' && renderMarkdown ? (
<div
className={classNames('markdown', styleSet.textContent + '')}
dangerouslySetInnerHTML={{ __html: renderMarkdown(text || '') }}
/>
<React.Fragment>
{/* Because of differences in browser implementations, <span aria-label> is used to make screenreader perform the same on different browsers */}
<span aria-label={text} />
<div
aria-hidden={true}
className={classNames('markdown', styleSet.textContent + '')}
dangerouslySetInnerHTML={{ __html: renderMarkdown(text || '') }}
/>
</React.Fragment>
) : (
(text || '').split('\n').map((line, index) => (
<p className={classNames('plain', styleSet.textContent + '')} key={index}>
{line.trim()}
</p>
<React.Fragment key={index}>
{/* Because of differences in browser implementations, <span aria-label> is used to make screenreader perform the same on different browsers */}
<span aria-label={text} />
<p aria-hidden={true} className={classNames('plain', styleSet.textContent + '')}>
{line.trim()}
</p>
</React.Fragment>
))
);

Expand Down
18 changes: 12 additions & 6 deletions packages/component/src/ErrorBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ import PropTypes from 'prop-types';
import React from 'react';

import connectToWebChat from './connectToWebChat';
import { localize } from './Localization/Localize';

const ErrorBox = ({ children, message, styleSet }) => (
<div className={styleSet.errorBox}>
<div>{message}</div>
<div>{children}</div>
</div>
);
const ErrorBox = ({ children, language, message, styleSet }) => {
const errorMessageLabel = localize('ErrorMessage', language);

return (
<div aria-label={errorMessageLabel} className={styleSet.errorBox}>
<div aria-label={message}>{message}</div>
<div>{children}</div>
</div>
);
};

ErrorBox.defaultProps = {
children: undefined,
Expand All @@ -17,6 +22,7 @@ ErrorBox.defaultProps = {

ErrorBox.propTypes = {
children: PropTypes.any,
language: PropTypes.string.isRequired,
message: PropTypes.string,
styleSet: PropTypes.shape({
errorBox: PropTypes.any.isRequired
Expand Down
11 changes: 11 additions & 0 deletions packages/component/src/Localization/en-US.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ function botSaidSomething(avatarInitials, text) {
return `Bot ${avatarInitials} said, ${text}`;
}

function downloadFileWithFileSize(downloadFileText, fileName, size) {
// Full text should read: "Download file <filename> of size <filesize>"
return `${downloadFileText} ${fileName} of size ${size}`;
}

function userSaidSomething(avatarInitials, text) {
return `User ${avatarInitials} said, ${text}`;
}
Expand All @@ -64,8 +69,11 @@ export default {
// '[Unknown Card '%1']': '[Unknown Card '%1']',
'Adaptive Card parse error': 'Adaptive Card parse error',
'Adaptive Card render error': 'Adaptive Card render error',
BotSent: 'Bot sent: ',
Chat: 'Chat',
'Download file': 'Download file',
DownloadFileWithFileSize: downloadFileWithFileSize,
ErrorMessage: 'Error message',
'Microphone off': 'Microphone off',
'Microphone on': 'Microphone on',
Left: 'Left',
Expand All @@ -75,11 +83,14 @@ export default {
Right: 'Right',
Send: 'Send',
Sending: 'Sending',
SendStatus: 'Send status: ',
SentAt: 'Sent at: ',
Speak: 'Speak',
'Starting…': 'Starting…',
Tax: 'Tax',
Total: 'Total',
'Type your message': 'Type your message',
'Upload file': 'Upload file',
UserSent: 'User sent: ',
VAT: 'VAT'
};

0 comments on commit b6298eb

Please sign in to comment.