Merge pull request #2596 from matrix-org/dbkr/emoji_sas

Change SAS to decimal / emoji
This commit is contained in:
David Baker 2019-02-08 16:46:43 +00:00 committed by GitHub
commit 2cd25e0077
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 224 additions and 18 deletions

View file

@ -14,9 +14,35 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
.mx_VerificationShowSas_sas { .mx_VerificationShowSas_decimalSas {
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
padding-left: 3px; padding-left: 3px;
padding-right: 3px; padding-right: 3px;
} }
.mx_VerificationShowSas_decimalSas span {
margin-left: 5px;
margin-right: 5px;
}
.mx_VerificationShowSas_emojiSas {
text-align: center;
}
.mx_VerificationShowSas_emojiSas_block {
display: inline-block;
margin-left: 15px;
margin-right: 15px;
text-align: center;
margin-bottom: 20px;
}
.mx_VerificationShowSas_emojiSas_emoji {
font-size: 48px;
}
.mx_VerificationShowSas_emojiSas_label {
text-align: center;
font-weight: bold;
}

View file

@ -68,8 +68,10 @@ export function containsEmoji(str) {
/* modified from https://github.com/Ranks/emojione/blob/master/lib/js/emojione.js /* modified from https://github.com/Ranks/emojione/blob/master/lib/js/emojione.js
* because we want to include emoji shortnames in title text * because we want to include emoji shortnames in title text
*/ */
function unicodeToImage(str) { function unicodeToImage(str, addAlt) {
let replaceWith; let unicode; let alt; let short; let fname; if (addAlt === undefined) addAlt = true;
let replaceWith; let unicode; let short; let fname;
const mappedUnicode = emojione.mapUnicodeToShort(); const mappedUnicode = emojione.mapUnicodeToShort();
str = str.replace(emojione.regUnicode, function(unicodeChar) { str = str.replace(emojione.regUnicode, function(unicodeChar) {
@ -84,10 +86,14 @@ function unicodeToImage(str) {
fname = emojione.emojioneList[short].fname; fname = emojione.emojioneList[short].fname;
// depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname
alt = (emojione.unicodeAlt) ? emojione.convert(unicode.toUpperCase()) : mappedUnicode[unicode];
const title = mappedUnicode[unicode]; const title = mappedUnicode[unicode];
if (addAlt) {
const alt = (emojione.unicodeAlt) ? emojione.convert(unicode.toUpperCase()) : mappedUnicode[unicode];
replaceWith = `<img class="mx_emojione" title="${title}" alt="${alt}" src="${emojione.imagePathSVG}${fname}.svg${emojione.cacheBustParam}"/>`; replaceWith = `<img class="mx_emojione" title="${title}" alt="${alt}" src="${emojione.imagePathSVG}${fname}.svg${emojione.cacheBustParam}"/>`;
} else {
replaceWith = `<img class="mx_emojione" src="${emojione.imagePathSVG}${fname}.svg${emojione.cacheBustParam}"/>`;
}
return replaceWith; return replaceWith;
} }
}); });
@ -508,9 +514,9 @@ export function bodyToHtml(content, highlights, opts={}) {
<span className={className} dir="auto">{ strippedBody }</span>; <span className={className} dir="auto">{ strippedBody }</span>;
} }
export function emojifyText(text) { export function emojifyText(text, addAlt) {
return { return {
__html: unicodeToImage(escape(text)), __html: unicodeToImage(escape(text), addAlt),
}; };
} }

View file

@ -20,12 +20,12 @@ import PropTypes from 'prop-types';
import {emojifyText, containsEmoji} from '../../../HtmlUtils'; import {emojifyText, containsEmoji} from '../../../HtmlUtils';
export default function EmojiText(props) { export default function EmojiText(props) {
const {element, children, ...restProps} = props; const {element, children, addAlt, ...restProps} = props;
// fast path: simple regex to detect strings that don't contain // fast path: simple regex to detect strings that don't contain
// emoji and just return them // emoji and just return them
if (containsEmoji(children)) { if (containsEmoji(children)) {
restProps.dangerouslySetInnerHTML = emojifyText(children); restProps.dangerouslySetInnerHTML = emojifyText(children, addAlt);
return React.createElement(element, restProps); return React.createElement(element, restProps);
} else { } else {
return React.createElement(element, restProps, children); return React.createElement(element, restProps, children);
@ -39,4 +39,5 @@ EmojiText.propTypes = {
EmojiText.defaultProps = { EmojiText.defaultProps = {
element: 'span', element: 'span',
addAlt: true,
}; };

View file

@ -17,13 +17,17 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import sdk from '../../../index'; import sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t, _td } from '../../../languageHandler';
function capFirst(s) {
return s.charAt(0).toUpperCase() + s.slice(1);
}
export default class VerificationShowSas extends React.Component { export default class VerificationShowSas extends React.Component {
static propTypes = { static propTypes = {
onDone: PropTypes.func.isRequired, onDone: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired, onCancel: PropTypes.func.isRequired,
sas: PropTypes.string.isRequired, sas: PropTypes.object.isRequired,
} }
constructor() { constructor() {
@ -32,17 +36,55 @@ export default class VerificationShowSas extends React.Component {
render() { render() {
const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
return <div className="mx_VerificationShowSas"> const EmojiText = sdk.getComponent('views.elements.EmojiText');
<p>{_t(
let sasDisplay;
let sasCaption;
if (this.props.sas.emoji) {
const emojiBlocks = this.props.sas.emoji.map(
(emoji, i) => <div className="mx_VerificationShowSas_emojiSas_block" key={i}>
<div className="mx_VerificationShowSas_emojiSas_emoji">
<EmojiText addAlt={false}>{emoji[0]}</EmojiText>
</div>
<div className="mx_VerificationShowSas_emojiSas_label">
{_t(capFirst(emoji[1]))}
</div>
</div>,
);
sasDisplay = <div className="mx_VerificationShowSas_emojiSas">
{emojiBlocks}
</div>;
sasCaption = _t(
"Verify this user by confirming the following emoji appear on their screen.",
);
} else if (this.props.sas.decimal) {
const numberBlocks = this.props.sas.decimal.map((num, i) => <span key={i}>
{num}
</span>);
sasDisplay = <div className="mx_VerificationShowSas_decimalSas">
{numberBlocks}
</div>;
sasCaption = _t(
"Verify this user by confirming the following number appears on their screen.", "Verify this user by confirming the following number appears on their screen.",
)}</p> );
} else {
return <div>
{_t("Unable to find a supported verification method.")}
<DialogButtons
primaryButton={_t('Cancel')}
hasCancel={false}
onPrimaryButtonClick={this.props.onCancel}
/>
</div>;
}
return <div className="mx_VerificationShowSas">
<p>{sasCaption}</p>
<p>{_t( <p>{_t(
"For maximum security, we recommend you do this in person or use another " + "For maximum security, we recommend you do this in person or use another " +
"trusted means of communication.", "trusted means of communication.",
)}</p> )}</p>
<div className="mx_VerificationShowSas_sas"> {sasDisplay}
{this.props.sas}
</div>
<DialogButtons onPrimaryButtonClick={this.props.onDone} <DialogButtons onPrimaryButtonClick={this.props.onDone}
primaryButton={_t("Continue")} primaryButton={_t("Continue")}
hasCancel={true} hasCancel={true}
@ -51,3 +93,69 @@ export default class VerificationShowSas extends React.Component {
</div>; </div>;
} }
} }
// List of Emoji strings from the js-sdk, for i18n
_td("Dog");
_td("Cat");
_td("Lion");
_td("Horse");
_td("Unicorn");
_td("Pig");
_td("Elephant");
_td("Rabbit");
_td("Panda");
_td("Rooster");
_td("Penguin");
_td("Turtle");
_td("Fish");
_td("Octopus");
_td("Butterfly");
_td("Flower");
_td("Tree");
_td("Cactus");
_td("Mushroom");
_td("Globe");
_td("Moon");
_td("Cloud");
_td("Fire");
_td("Banana");
_td("Apple");
_td("Strawberry");
_td("Corn");
_td("Pizza");
_td("Cake");
_td("Heart");
_td("Smiley");
_td("Robot");
_td("Hat");
_td("Glasses");
_td("Spanner");
_td("Santa");
_td("Thumbs up");
_td("Umbrella");
_td("Hourglass");
_td("Clock");
_td("Gift");
_td("Light bulb");
_td("Book");
_td("Pencil");
_td("Paperclip");
_td("Scisors");
_td("Padlock");
_td("Key");
_td("Hammer");
_td("Telephone");
_td("Flag");
_td("Train");
_td("Bicycle");
_td("Aeroplane");
_td("Rocket");
_td("Trophy");
_td("Ball");
_td("Guitar");
_td("Trumpet");
_td("Bell");
_td("Anchor");
_td("Headphones");
_td("Folder");
_td("Pin");

View file

@ -333,10 +333,75 @@
"You've successfully verified this user.": "You've successfully verified this user.", "You've successfully verified this user.": "You've successfully verified this user.",
"Secure messages with this user are end-to-end encrypted and not able to be read by third parties.": "Secure messages with this user are end-to-end encrypted and not able to be read by third parties.", "Secure messages with this user are end-to-end encrypted and not able to be read by third parties.": "Secure messages with this user are end-to-end encrypted and not able to be read by third parties.",
"Got It": "Got It", "Got It": "Got It",
"Verify this user by confirming the following emoji appear on their screen.": "Verify this user by confirming the following emoji appear on their screen.",
"Verify this user by confirming the following number appears on their screen.": "Verify this user by confirming the following number appears on their screen.", "Verify this user by confirming the following number appears on their screen.": "Verify this user by confirming the following number appears on their screen.",
"Unable to find a supported verification method.": "Unable to find a supported verification method.",
"For maximum security, we recommend you do this in person or use another trusted means of communication.": "For maximum security, we recommend you do this in person or use another trusted means of communication.", "For maximum security, we recommend you do this in person or use another trusted means of communication.": "For maximum security, we recommend you do this in person or use another trusted means of communication.",
"To continue, click on each pair to confirm it's correct.": "To continue, click on each pair to confirm it's correct.",
"Continue": "Continue", "Continue": "Continue",
"Dog": "Dog",
"Cat": "Cat",
"Lion": "Lion",
"Horse": "Horse",
"Unicorn": "Unicorn",
"Pig": "Pig",
"Elephant": "Elephant",
"Rabbit": "Rabbit",
"Panda": "Panda",
"Rooster": "Rooster",
"Penguin": "Penguin",
"Turtle": "Turtle",
"Fish": "Fish",
"Octopus": "Octopus",
"Butterfly": "Butterfly",
"Flower": "Flower",
"Tree": "Tree",
"Cactus": "Cactus",
"Mushroom": "Mushroom",
"Globe": "Globe",
"Moon": "Moon",
"Cloud": "Cloud",
"Fire": "Fire",
"Banana": "Banana",
"Apple": "Apple",
"Strawberry": "Strawberry",
"Corn": "Corn",
"Pizza": "Pizza",
"Cake": "Cake",
"Heart": "Heart",
"Smiley": "Smiley",
"Robot": "Robot",
"Hat": "Hat",
"Glasses": "Glasses",
"Wrench": "Wrench",
"Santa": "Santa",
"Thumbs up": "Thumbs up",
"Umbrella": "Umbrella",
"Hourglass": "Hourglass",
"Clock": "Clock",
"Gift": "Gift",
"Light bulb": "Light bulb",
"Book": "Book",
"Pencil": "Pencil",
"Paperclip": "Paperclip",
"Scisors": "Scisors",
"Padlock": "Padlock",
"Key": "Key",
"Hammer": "Hammer",
"Telephone": "Telephone",
"Flag": "Flag",
"Train": "Train",
"Bicycle": "Bicycle",
"Aeroplane": "Aeroplane",
"Rocket": "Rocket",
"Trophy": "Trophy",
"Ball": "Ball",
"Guitar": "Guitar",
"Trumpet": "Trumpet",
"Bell": "Bell",
"Anchor": "Anchor",
"Headphones": "Headphones",
"Folder": "Folder",
"Pin": "Pin",
"Failed to upload profile picture!": "Failed to upload profile picture!", "Failed to upload profile picture!": "Failed to upload profile picture!",
"Upload new:": "Upload new:", "Upload new:": "Upload new:",
"No display name": "No display name", "No display name": "No display name",