Right-to-left CSS (using module for conversion) (#7072)

* Create RTL stylesheets using `gulp-rtl`

* Handle RTL stylesheet special cases

Certain blocks of Sass  were set to bypass "rtlcss" using ignore
comments. Certain icons had to be flipped 180 degrees.

* Switch stylesheets when locale changes

A second stylesheet has been added to each HTML page for use with
right-to-left locales. It is disabled by default. It is enabled on
startup if a RTL locale is set, and when switching to a RTL locale.
Similarly the LTR stylesheet is disabled when a RTL locale is used.

Unfortunately there is an unpleasant flash of unstyled content when
switching between a LTR and a RTL locale. There is also a slightly
longer page load time when using a RTL locale (<1s difference). We
couldn't think of an easy way to avoid these problems.

* Set `dir="auto"` as default on `TextFields`
feature/default_network_editable
Nick Doiron 5 years ago committed by Mark Stacey
parent 361a19a850
commit d589d2dec0
  1. 3
      app/home.html
  2. 3
      app/notification.html
  3. 3
      app/popup.html
  4. 7
      app/scripts/controllers/preferences.js
  5. 4
      app/scripts/metamask-controller.js
  6. 9
      gulpfile.js
  7. 2
      package.json
  8. 4
      ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss
  9. 3
      ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss
  10. 5
      ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss
  11. 3
      ui/app/components/ui/currency-display/index.scss
  12. 1
      ui/app/components/ui/editable-label.js
  13. 2
      ui/app/components/ui/identicon/index.scss
  14. 51
      ui/app/components/ui/sender-to-recipient/index.scss
  15. 6
      ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js
  16. 7
      ui/app/components/ui/text-field/text-field.component.js
  17. 1
      ui/app/components/ui/unit-input/unit-input.component.js
  18. 2
      ui/app/css/itcss/components/modal.scss
  19. 12
      ui/app/css/itcss/components/newui-sections.scss
  20. 2
      ui/app/css/itcss/components/sections.scss
  21. 4
      ui/app/css/itcss/components/tab-bar.scss
  22. 30
      ui/app/helpers/utils/switch-direction.js
  23. 2
      ui/app/pages/add-token/token-list/index.scss
  24. 2
      ui/app/pages/first-time-flow/index.scss
  25. 2
      ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss
  26. 4
      ui/app/pages/routes/index.js
  27. 1
      ui/app/pages/send/send-content/add-recipient/ens-input.component.js
  28. 4
      ui/app/pages/send/send.scss
  29. 1
      ui/app/pages/send/to-autocomplete/to-autocomplete.js
  30. 4
      ui/app/pages/settings/contact-list-tab/index.scss
  31. 12
      ui/app/pages/settings/index.scss
  32. 8
      ui/app/pages/settings/networks-tab/index.scss
  33. 7
      ui/app/store/actions.js
  34. 1
      ui/index.html
  35. 5
      ui/index.js
  36. 65
      yarn.lock

@ -4,7 +4,8 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=no">
<title>MetaMask</title> <title>MetaMask</title>
<link rel="stylesheet" type="text/css" href="./index.css"> <link rel="stylesheet" type="text/css" href="./index.css" title="ltr">
<link rel="stylesheet" type="text/css" href="./index-rtl.css" title="rtl" disabled>
</head> </head>
<body> <body>
<div id="app-content"></div> <div id="app-content"></div>

@ -28,7 +28,8 @@
margin-top: 1rem; margin-top: 1rem;
} }
</style> </style>
<link rel="stylesheet" type="text/css" href="./index.css"> <link rel="stylesheet" type="text/css" href="./index.css" title="ltr">
<link rel="stylesheet" type="text/css" href="./index-rtl.css" title="rtl" disabled>
</head> </head>
<body class="notification" style="height:600px;"> <body class="notification" style="height:600px;">
<div id="app-content"> <div id="app-content">

@ -4,7 +4,8 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=no">
<title>MetaMask</title> <title>MetaMask</title>
<link rel="stylesheet" type="text/css" href="./index.css"> <link rel="stylesheet" type="text/css" href="./index.css" title="ltr">
<link rel="stylesheet" type="text/css" href="./index-rtl.css" title="rtl" disabled>
</head> </head>
<body style="width:357px; height:600px;"> <body style="width:357px; height:600px;">
<div id="app-content"></div> <div id="app-content"></div>

@ -211,7 +211,12 @@ class PreferencesController {
* *
*/ */
setCurrentLocale (key) { setCurrentLocale (key) {
this.store.updateState({ currentLocale: key }) const textDirection = (['ar', 'dv', 'fa', 'he', 'ku'].includes(key)) ? 'rtl' : 'auto'
this.store.updateState({
currentLocale: key,
textDirection: textDirection,
})
return textDirection
} }
/** /**

@ -1723,8 +1723,8 @@ module.exports = class MetamaskController extends EventEmitter {
*/ */
setCurrentLocale (key, cb) { setCurrentLocale (key, cb) {
try { try {
this.preferencesController.setCurrentLocale(key) const direction = this.preferencesController.setCurrentLocale(key)
cb(null) cb(null, direction)
} catch (err) { } catch (err) {
cb(err) cb(err)
} }

@ -19,6 +19,8 @@ const gulpStylelint = require('gulp-stylelint')
const stylefmt = require('gulp-stylefmt') const stylefmt = require('gulp-stylefmt')
const uglify = require('gulp-uglify-es').default const uglify = require('gulp-uglify-es').default
const pify = require('pify') const pify = require('pify')
const rtlcss = require('gulp-rtlcss')
const rename = require('gulp-rename')
const gulpMultiProcess = require('gulp-multi-process') const gulpMultiProcess = require('gulp-multi-process')
const endOfStream = pify(require('end-of-stream')) const endOfStream = pify(require('end-of-stream'))
@ -274,6 +276,10 @@ function createScssBuildTask ({ src, dest, devMode, pattern }) {
.pipe(sourcemaps.write()) .pipe(sourcemaps.write())
.pipe(autoprefixer()) .pipe(autoprefixer())
.pipe(gulp.dest(dest)) .pipe(gulp.dest(dest))
.pipe(rtlcss())
.pipe(rename({ suffix: '-rtl' }))
.pipe(sourcemaps.write())
.pipe(gulp.dest(dest))
} }
function buildScss () { function buildScss () {
@ -281,6 +287,9 @@ function createScssBuildTask ({ src, dest, devMode, pattern }) {
.pipe(sass().on('error', sass.logError)) .pipe(sass().on('error', sass.logError))
.pipe(autoprefixer()) .pipe(autoprefixer())
.pipe(gulp.dest(dest)) .pipe(gulp.dest(dest))
.pipe(rtlcss())
.pipe(rename({ suffix: '-rtl' }))
.pipe(gulp.dest(dest))
} }
} }

@ -218,7 +218,9 @@
"gulp-json-editor": "^2.2.1", "gulp-json-editor": "^2.2.1",
"gulp-livereload": "4.0.0", "gulp-livereload": "4.0.0",
"gulp-multi-process": "^1.3.1", "gulp-multi-process": "^1.3.1",
"gulp-rename": "^1.4.0",
"gulp-replace": "^0.6.1", "gulp-replace": "^0.6.1",
"gulp-rtlcss": "^1.4.0",
"gulp-sass": "^4.0.0", "gulp-sass": "^4.0.0",
"gulp-sourcemaps": "^2.6.0", "gulp-sourcemaps": "^2.6.0",
"gulp-stylefmt": "^1.1.0", "gulp-stylefmt": "^1.1.0",

@ -15,6 +15,10 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
[dir='rtl'] & img {
transform: rotate(180deg);
}
} }
&__back-button { &__back-button {

@ -47,6 +47,8 @@
} }
&__input { &__input {
/*rtl:ignore*/
direction: ltr;
border: 1px solid $dusty-gray; border: 1px solid $dusty-gray;
border-radius: 4px; border-radius: 4px;
color: $mid-gray; color: $mid-gray;
@ -69,6 +71,7 @@
&__input-arrows { &__input-arrows {
position: absolute; position: absolute;
top: 7px; top: 7px;
/*rtl:ignore*/
right: 0px; right: 0px;
width: 17px; width: 17px;
height: 24px; height: 24px;

@ -36,6 +36,8 @@
} }
&__time-remaining { &__time-remaining {
/*rtl:ignore*/
direction: ltr;
color: #313A5E; color: #313A5E;
font-size: 16px; font-size: 16px;
@ -137,6 +139,8 @@
} }
&__input { &__input {
/*rtl:ignore*/
direction: ltr;
border: 1px solid $dusty-gray; border: 1px solid $dusty-gray;
border-radius: 4px; border-radius: 4px;
color: $mid-gray; color: $mid-gray;
@ -159,6 +163,7 @@
&__input-arrows { &__input-arrows {
position: absolute; position: absolute;
top: 7px; top: 7px;
/*rtl:ignore*/
right: 0px; right: 0px;
width: 17px; width: 17px;
height: 24px; height: 24px;

@ -3,10 +3,11 @@
align-items: center; align-items: center;
&__text { &__text {
/*rtl:ignore*/
direction: ltr;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
&__suffix { &__suffix {

@ -37,6 +37,7 @@ class EditableLabel extends Component {
h('input.large-input.editable-label__input', { h('input.large-input.editable-label__input', {
type: 'text', type: 'text',
required: true, required: true,
dir: 'auto',
value: this.state.value, value: this.state.value,
onKeyPress: (event) => { onKeyPress: (event) => {
if (event.key === 'Enter') { if (event.key === 'Enter') {

@ -1,4 +1,6 @@
.identicon { .identicon {
/*rtl:ignore*/
direction: ltr;
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;

@ -50,6 +50,10 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
[dir='rtl'] & {
transform: rotate(180deg);
}
} }
&__arrow-circle { &__arrow-circle {
@ -70,6 +74,19 @@
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
font-size: .875rem; font-size: .875rem;
[dir='rtl'] & {
/*rtl:ignore*/
direction: ltr;
/*rtl:ignore*/
text-align: right;
span {
display: block;
/*rtl:ignore*/
direction: rtl;
}
}
} }
} }
} }
@ -102,12 +119,29 @@
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
font-size: .5rem; font-size: .5rem;
[dir='rtl'] & {
/*rtl:ignore*/
direction: ltr;
/*rtl:ignore*/
text-align: right;
span {
display: block;
/*rtl:ignore*/
direction: rtl;
}
}
} }
&__arrow-container { &__arrow-container {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
[dir='rtl'] & {
transform: rotate(180deg);
}
} }
} }
} }
@ -137,12 +171,29 @@
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
font-size: .6875rem; font-size: .6875rem;
[dir='rtl'] & {
/*rtl:ignore*/
direction: ltr;
/*rtl:ignore*/
text-align: right;
span {
display: block;
/*rtl:ignore*/
direction: rtl;
}
}
} }
&__arrow-container { &__arrow-container {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
[dir='rtl'] & {
transform: rotate(180deg);
}
} }
} }
} }

@ -66,7 +66,8 @@ export default class SenderToRecipient extends PureComponent {
onHidden={() => this.setState({ senderAddressCopied: false })} onHidden={() => this.setState({ senderAddressCopied: false })}
> >
<div className="sender-to-recipient__name"> <div className="sender-to-recipient__name">
{ addressOnly ? `${t('from')}: ${checksummedSenderAddress}` : senderName } <span>{ addressOnly ? `${t('from')}: ` : '' }</span>
{ addressOnly ? checksummedSenderAddress : senderName }
</div> </div>
</Tooltip> </Tooltip>
) )
@ -112,9 +113,10 @@ export default class SenderToRecipient extends PureComponent {
onHidden={() => this.setState({ recipientAddressCopied: false })} onHidden={() => this.setState({ recipientAddressCopied: false })}
> >
<div className="sender-to-recipient__name"> <div className="sender-to-recipient__name">
<span>{ addressOnly ? `${t('to')}: ` : '' }</span>
{ {
addressOnly addressOnly
? `${t('to')}: ${checksummedRecipientAddress}` ? checksummedRecipientAddress
: (recipientNickname || recipientName || this.context.t('newContract')) : (recipientNickname || recipientName || this.context.t('newContract'))
} }
</div> </div>

@ -67,7 +67,7 @@ const styles = {
} }
const TextField = props => { const TextField = props => {
const { error, classes, material, startAdornment, largeLabel, ...textFieldProps } = props const { error, classes, material, startAdornment, largeLabel, dir, ...textFieldProps } = props
return ( return (
<MaterialTextField <MaterialTextField
@ -91,6 +91,9 @@ const TextField = props => {
underline: material ? classes.materialUnderline : '', underline: material ? classes.materialUnderline : '',
focused: material ? '' : classes.inputFocused, focused: material ? '' : classes.inputFocused,
}, },
inputProps: {
dir,
},
}} }}
{...textFieldProps} {...textFieldProps}
/> />
@ -99,11 +102,13 @@ const TextField = props => {
TextField.defaultProps = { TextField.defaultProps = {
error: null, error: null,
dir: 'auto',
} }
TextField.propTypes = { TextField.propTypes = {
error: PropTypes.string, error: PropTypes.string,
classes: PropTypes.object, classes: PropTypes.object,
dir: PropTypes.string,
material: PropTypes.bool, material: PropTypes.bool,
startAdornment: PropTypes.element, startAdornment: PropTypes.element,
largeLabel: PropTypes.bool, largeLabel: PropTypes.bool,

@ -84,6 +84,7 @@ export default class UnitInput extends PureComponent {
<div className="unit-input__input-container"> <div className="unit-input__input-container">
<input <input
type="number" type="number"
dir="ltr"
className={classnames('unit-input__input', { 'unit-input__disabled': maxModeOn })} className={classnames('unit-input__input', { 'unit-input__disabled': maxModeOn })}
value={value} value={value}
placeholder={placeholder} placeholder={placeholder}

@ -18,6 +18,8 @@
} }
.qr-ellip-address, .ellip-address { .qr-ellip-address, .ellip-address {
/*rtl:ignore*/
direction: ltr;
width: 247px; width: 247px;
border: none; border: none;
font-family: Roboto; font-family: Roboto;

@ -57,6 +57,13 @@ $wallet-view-bg: $alabaster;
z-index: 200; z-index: 200;
position: relative; position: relative;
[dir='rtl'] & i.fa.fa-clipboard {
/*rtl:ignore*/
margin-left: 0 !important;
/*rtl:ignore*/
margin-right: 8px !important;
}
@media screen and (min-width: 576px) { @media screen and (min-width: 576px) {
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden; overflow-x: hidden;
@ -103,6 +110,11 @@ $wallet-view-bg: $alabaster;
box-shadow: rgba(0, 0, 0, .15) 2px 2px 4px; box-shadow: rgba(0, 0, 0, .15) 2px 2px 4px;
width: 85%; width: 85%;
height: calc(100% - 56px); height: calc(100% - 56px);
[dir='rtl'] & {
/* rtl:ignore */
left: 15%;
}
} }
// main-container media queries // main-container media queries

@ -414,6 +414,8 @@ textarea.twelve-word-phrase {
} }
.qr-ellip-address, .ellip-address { .qr-ellip-address, .ellip-address {
/*rtl:ignore*/
direction: ltr;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

@ -62,6 +62,10 @@
background-size: contain; background-size: contain;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
[dir='rtl'] & {
transform: rotate(180deg);
}
} }
} }

@ -0,0 +1,30 @@
/**
* Switch the CSS stylesheet used between 'rtl' and 'ltr'
* @param {('ltr' | 'rtl')} direction Text direction, either left-to-right (ltr) or right-to-left (rtl)
*/
const switchDirection = async (direction) => {
if (direction === 'auto') {
direction = 'ltr'
}
let updatedLink
Array.from(document.getElementsByTagName('link'))
.filter(link => link.rel === 'stylesheet')
.forEach(link => {
if (link.title === direction && link.disabled) {
link.disabled = false
updatedLink = link
} else if (link.title !== direction && !link.disabled) {
link.disabled = true
}
})
if (updatedLink) {
return new Promise((resolve, reject) => {
updatedLink.onload = () => {
resolve()
}
updatedLink.onerror = () => reject(new Error(`Failed to load '${direction}' stylesheet`))
})
}
}
export default switchDirection

@ -58,6 +58,8 @@
} }
&__token-name { &__token-name {
/*rtl:ignore*/
direction: ltr;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;

@ -73,6 +73,8 @@
} }
&__textarea { &__textarea {
/*rtl:ignore*/
direction: ltr;
font-size: 1rem; font-size: 1rem;
font-family: Roboto; font-family: Roboto;
height: 190px; height: 190px;

@ -64,6 +64,8 @@
} }
&__selected-seed-words { &__selected-seed-words {
/*rtl:ignore*/
direction: ltr;
display: flex; display: flex;
flex-flow: row wrap; flex-flow: row wrap;
min-height: 161px; min-height: 161px;

@ -170,6 +170,7 @@ class Routes extends Component {
const { const {
isLoading, isLoading,
alertMessage, alertMessage,
textDirection,
loadingMessage, loadingMessage,
network, network,
provider, provider,
@ -208,6 +209,7 @@ class Routes extends Component {
return ( return (
<div <div
className={classnames('app', { 'mouse-user-styles': isMouseUser})} className={classnames('app', { 'mouse-user-styles': isMouseUser})}
dir={textDirection}
onClick={() => setMouseUserState(true)} onClick={() => setMouseUserState(true)}
onKeyDown={e => { onKeyDown={e => {
if (e.keyCode === 9) { if (e.keyCode === 9) {
@ -323,6 +325,7 @@ Routes.propTypes = {
isLoading: PropTypes.bool, isLoading: PropTypes.bool,
loadingMessage: PropTypes.string, loadingMessage: PropTypes.string,
alertMessage: PropTypes.string, alertMessage: PropTypes.string,
textDirection: PropTypes.string,
network: PropTypes.string, network: PropTypes.string,
provider: PropTypes.object, provider: PropTypes.object,
frequentRpcListDetail: PropTypes.array, frequentRpcListDetail: PropTypes.array,
@ -360,6 +363,7 @@ function mapStateToProps (state) {
sidebar, sidebar,
alertOpen, alertOpen,
alertMessage, alertMessage,
textDirection: state.metamask.textDirection,
isLoading, isLoading,
loadingMessage, loadingMessage,
isUnlocked: state.metamask.isUnlocked, isUnlocked: state.metamask.isUnlocked,

@ -155,6 +155,7 @@ export default class EnsInput extends Component {
<input <input
className="ens-input__wrapper__input" className="ens-input__wrapper__input"
type="text" type="text"
dir="auto"
placeholder={t('recipientAddressPlaceholder')} placeholder={t('recipientAddressPlaceholder')}
onChange={this.onChange} onChange={this.onChange}
onPaste={this.onPaste} onPaste={this.onPaste}

@ -60,6 +60,10 @@
width: 18px; width: 18px;
height: 18px; height: 18px;
margin-right: .5rem; margin-right: .5rem;
[dir='rtl'] & {
transform: rotate(180deg);
}
} }
} }

@ -99,6 +99,7 @@ ToAutoComplete.prototype.render = function () {
h(`input.send-v2__to-autocomplete__input${qrScanner ? '.with-qr' : ''}`, { h(`input.send-v2__to-autocomplete__input${qrScanner ? '.with-qr' : ''}`, {
placeholder: this.context.t('recipientAddress'), placeholder: this.context.t('recipientAddress'),
className: inError ? `send-v2__error-border` : '', className: inError ? `send-v2__error-border` : '',
dir: 'auto',
value: to, value: to,
onChange: event => onChange(event.target.value), onChange: event => onChange(event.target.value),
onFocus: event => this.handleInputEvent(event), onFocus: event => this.handleInputEvent(event),

@ -197,6 +197,10 @@
width: 30px; width: 30px;
opacity: .5; opacity: .5;
background-repeat: no-repeat; background-repeat: no-repeat;
[dir='rtl'] & {
transform: rotate(180deg);
}
} }
} }
} }

@ -97,6 +97,10 @@
background-position: center; background-position: center;
margin-right: 16px; margin-right: 16px;
cursor: pointer; cursor: pointer;
[dir='rtl'] & {
transform: rotate(180deg);
}
} }
} }
@ -244,4 +248,12 @@
} }
} }
} }
.toggle-button {
/*rtl:ignore*/
direction: ltr;
[dir='rtl'] & {
justify-content: flex-end;
}
}
} }

@ -38,6 +38,10 @@
cursor: pointer; cursor: pointer;
position: absolute; position: absolute;
margin-left: 10px; margin-left: 10px;
[dir='rtl'] & {
transform: rotate(180deg);
}
} }
} }
@ -190,6 +194,10 @@
position: absolute; position: absolute;
width: 24px; width: 24px;
height: 24px; height: 24px;
[dir='rtl'] & {
transform: rotate(180deg);
}
} }
} }

@ -10,6 +10,7 @@ const ethUtil = require('ethereumjs-util')
const { fetchLocale } = require('../helpers/utils/i18n-helper') const { fetchLocale } = require('../helpers/utils/i18n-helper')
const { getMethodDataAsync } = require('../helpers/utils/transactions.util') const { getMethodDataAsync } = require('../helpers/utils/transactions.util')
const { fetchSymbolAndDecimals } = require('../helpers/utils/token-util') const { fetchSymbolAndDecimals } = require('../helpers/utils/token-util')
import switchDirection from '../helpers/utils/switch-direction'
const log = require('loglevel') const log = require('loglevel')
const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../../app/scripts/lib/enums') const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../../app/scripts/lib/enums')
const { hasUnconfirmedTransactions } = require('../helpers/utils/confirm-tx.util') const { hasUnconfirmedTransactions } = require('../helpers/utils/confirm-tx.util')
@ -2597,11 +2598,13 @@ function updateCurrentLocale (key) {
return fetchLocale(key) return fetchLocale(key)
.then((localeMessages) => { .then((localeMessages) => {
log.debug(`background.setCurrentLocale`) log.debug(`background.setCurrentLocale`)
background.setCurrentLocale(key, (err) => { background.setCurrentLocale(key, (err, textDirection) => {
dispatch(actions.hideLoadingIndication())
if (err) { if (err) {
dispatch(actions.hideLoadingIndication())
return dispatch(actions.displayWarning(err.message)) return dispatch(actions.displayWarning(err.message))
} }
switchDirection(textDirection)
dispatch(actions.hideLoadingIndication())
dispatch(actions.setCurrentLocale(key)) dispatch(actions.setCurrentLocale(key))
dispatch(actions.setLocaleMessages(localeMessages)) dispatch(actions.setLocaleMessages(localeMessages))
}) })

@ -12,6 +12,7 @@
<!-- design reference --> <!-- design reference -->
<link rel="stylesheet" type="text/css" href="./app/css/debug.css"> <link rel="stylesheet" type="text/css" href="./app/css/debug.css">
<link rel="stylesheet" type="text/css" href="./app/css/debug-rtl.css" disabled="true">
<div id="design-container"> <div id="design-container">
<img id="design-img" src="./design/metamask_wfs_jan_13.png"> <img id="design-img" src="./design/metamask_wfs_jan_13.png">
</div> </div>

@ -5,6 +5,7 @@ const actions = require('./app/store/actions')
const configureStore = require('./app/store/store') const configureStore = require('./app/store/store')
const txHelper = require('./lib/tx-helper') const txHelper = require('./lib/tx-helper')
const { fetchLocale } = require('./app/helpers/utils/i18n-helper') const { fetchLocale } = require('./app/helpers/utils/i18n-helper')
import switchDirection from './app/helpers/utils/switch-direction'
const log = require('loglevel') const log = require('loglevel')
module.exports = launchMetamaskUi module.exports = launchMetamaskUi
@ -33,6 +34,10 @@ async function startApp (metamaskState, backgroundConnection, opts) {
: {} : {}
const enLocaleMessages = await fetchLocale('en') const enLocaleMessages = await fetchLocale('en')
if (metamaskState.textDirection === 'rtl') {
await switchDirection('rtl')
}
const store = configureStore({ const store = configureStore({
activeTab: opts.activeTab, activeTab: opts.activeTab,

@ -5728,6 +5728,11 @@ colors@^1.1.0, colors@^1.1.2:
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==
colors@~0.6.0-1:
version "0.6.2"
resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc"
integrity sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=
columnify@1.5.4: columnify@1.5.4:
version "1.5.4" version "1.5.4"
resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb"
@ -5806,6 +5811,11 @@ commander@^2.8.1, commander@~2.8.1:
dependencies: dependencies:
graceful-readlink ">= 1.0.0" graceful-readlink ">= 1.0.0"
commander@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781"
integrity sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E=
commander@~2.19.0: commander@~2.19.0:
version "2.19.0" version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
@ -9851,6 +9861,14 @@ findup-sync@^3.0.0:
micromatch "^3.0.4" micromatch "^3.0.4"
resolve-dir "^1.0.1" resolve-dir "^1.0.1"
findup@^0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/findup/-/findup-0.1.5.tgz#8ad929a3393bac627957a7e5de4623b06b0e2ceb"
integrity sha1-itkpozk7rGJ5V6fl3kYjsGsOLOs=
dependencies:
colors "~0.6.0-1"
commander "~2.1.0"
fined@^1.0.1: fined@^1.0.1:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476" resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476"
@ -11039,6 +11057,11 @@ gulp-multi-process@^1.3.1:
dependencies: dependencies:
async.queue "^0.5.2" async.queue "^0.5.2"
gulp-rename@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.4.0.tgz#de1c718e7c4095ae861f7296ef4f3248648240bd"
integrity sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==
gulp-replace@^0.6.1: gulp-replace@^0.6.1:
version "0.6.1" version "0.6.1"
resolved "https://registry.yarnpkg.com/gulp-replace/-/gulp-replace-0.6.1.tgz#11bf8c8fce533e33e2f6a8f2f430b955ba0be066" resolved "https://registry.yarnpkg.com/gulp-replace/-/gulp-replace-0.6.1.tgz#11bf8c8fce533e33e2f6a8f2f430b955ba0be066"
@ -11048,6 +11071,16 @@ gulp-replace@^0.6.1:
readable-stream "^2.0.1" readable-stream "^2.0.1"
replacestream "^4.0.0" replacestream "^4.0.0"
gulp-rtlcss@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/gulp-rtlcss/-/gulp-rtlcss-1.4.0.tgz#a1e4caef39182af03778cb9c18add9d3ee5e1c97"
integrity sha512-66UmUSacTzdV3L0KcsdwzExEu1+dTfNlq3emUZGgHPLgUaCrsZUgZwjsgKjPwkYJUZOucLpjOxAkB37k+H80Kw==
dependencies:
plugin-error "^1.0.1"
rtlcss "^2.4.0"
through2 "^2.0.5"
vinyl-sourcemaps-apply "^0.2.1"
gulp-sass@^4.0.0: gulp-sass@^4.0.0:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-4.0.1.tgz#7f43d117eb2d303524968a1b48494af1bc64d1d9" resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-4.0.1.tgz#7f43d117eb2d303524968a1b48494af1bc64d1d9"
@ -16768,6 +16801,15 @@ postcss@^6.0.1, postcss@^6.0.19:
source-map "^0.6.1" source-map "^0.6.1"
supports-color "^5.2.0" supports-color "^5.2.0"
postcss@^6.0.14:
version "6.0.23"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
dependencies:
chalk "^2.4.1"
source-map "^0.6.1"
supports-color "^5.4.0"
postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.5, postcss@^7.0.6: postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.5, postcss@^7.0.6:
version "7.0.17" version "7.0.17"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f"
@ -18010,7 +18052,7 @@ readable-stream@1.1, readable-stream@1.1.x, "readable-stream@>=1.1.13-1 <1.2.0-0
isarray "0.0.1" isarray "0.0.1"
string_decoder "~0.10.x" string_decoder "~0.10.x"
readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6: readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
version "2.3.6" version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
@ -18883,6 +18925,17 @@ rtcpeerconnection-shim@^1.2.10:
dependencies: dependencies:
sdp "^2.6.0" sdp "^2.6.0"
rtlcss@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-2.4.0.tgz#482ea28f2b9fe06dd0ab3057997be9af13da84c1"
integrity sha512-hdjFhZ5FCI0ABOfyXOMOhBtwPWtANLCG7rOiOcRf+yi5eDdxmDjqBruWouEnwVdzfh/TWF6NNncIEsigOCFZOA==
dependencies:
chalk "^2.3.0"
findup "^0.1.5"
mkdirp "^0.5.1"
postcss "^6.0.14"
strip-json-comments "^2.0.0"
run-async@^0.1.0: run-async@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
@ -20573,7 +20626,7 @@ strip-json-comments@1.0.x:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"
integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E= integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=
strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: strip-json-comments@^2.0.0, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
@ -21276,6 +21329,14 @@ through2@^1.1.1:
readable-stream ">=1.1.13-1 <1.2.0-0" readable-stream ">=1.1.13-1 <1.2.0-0"
xtend ">=4.0.0 <4.1.0-0" xtend ">=4.0.0 <4.1.0-0"
through2@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
dependencies:
readable-stream "~2.3.6"
xtend "~4.0.1"
through2@~0.2.3: through2@~0.2.3:
version "0.2.3" version "0.2.3"
resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f" resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f"

Loading…
Cancel
Save