aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Doiron <ndoiron@mapmeld.com>2019-09-04 01:47:54 +0800
committerMark Stacey <markjstacey@gmail.com>2019-09-04 01:47:54 +0800
commitd589d2dec09f8a14fdff1c632990a5eaba34a8c8 (patch)
tree63cb9f393f7c5b575249685a37d29b0d80865f45
parent361a19a85043c19c0bc8e06365f7e482cb6a4c9b (diff)
downloadtangerine-wallet-browser-d589d2dec09f8a14fdff1c632990a5eaba34a8c8.tar.gz
tangerine-wallet-browser-d589d2dec09f8a14fdff1c632990a5eaba34a8c8.tar.zst
tangerine-wallet-browser-d589d2dec09f8a14fdff1c632990a5eaba34a8c8.zip
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`
-rw-r--r--app/home.html3
-rw-r--r--app/notification.html3
-rw-r--r--app/popup.html3
-rw-r--r--app/scripts/controllers/preferences.js7
-rw-r--r--app/scripts/metamask-controller.js4
-rw-r--r--gulpfile.js9
-rw-r--r--package.json2
-rw-r--r--ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss4
-rw-r--r--ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss3
-rw-r--r--ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss5
-rw-r--r--ui/app/components/ui/currency-display/index.scss3
-rw-r--r--ui/app/components/ui/editable-label.js1
-rw-r--r--ui/app/components/ui/identicon/index.scss2
-rw-r--r--ui/app/components/ui/sender-to-recipient/index.scss51
-rw-r--r--ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js6
-rw-r--r--ui/app/components/ui/text-field/text-field.component.js7
-rw-r--r--ui/app/components/ui/unit-input/unit-input.component.js1
-rw-r--r--ui/app/css/itcss/components/modal.scss2
-rw-r--r--ui/app/css/itcss/components/newui-sections.scss12
-rw-r--r--ui/app/css/itcss/components/sections.scss2
-rw-r--r--ui/app/css/itcss/components/tab-bar.scss4
-rw-r--r--ui/app/helpers/utils/switch-direction.js30
-rw-r--r--ui/app/pages/add-token/token-list/index.scss2
-rw-r--r--ui/app/pages/first-time-flow/index.scss2
-rw-r--r--ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss2
-rw-r--r--ui/app/pages/routes/index.js4
-rw-r--r--ui/app/pages/send/send-content/add-recipient/ens-input.component.js1
-rw-r--r--ui/app/pages/send/send.scss4
-rw-r--r--ui/app/pages/send/to-autocomplete/to-autocomplete.js1
-rw-r--r--ui/app/pages/settings/contact-list-tab/index.scss4
-rw-r--r--ui/app/pages/settings/index.scss12
-rw-r--r--ui/app/pages/settings/networks-tab/index.scss8
-rw-r--r--ui/app/store/actions.js7
-rw-r--r--ui/index.html1
-rw-r--r--ui/index.js5
-rw-r--r--yarn.lock65
36 files changed, 268 insertions, 14 deletions
diff --git a/app/home.html b/app/home.html
index ac17ed307..649727bbd 100644
--- a/app/home.html
+++ b/app/home.html
@@ -4,7 +4,8 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=no">
<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>
<body>
<div id="app-content"></div>
diff --git a/app/notification.html b/app/notification.html
index eba290c15..453716d1c 100644
--- a/app/notification.html
+++ b/app/notification.html
@@ -28,7 +28,8 @@
margin-top: 1rem;
}
</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>
<body class="notification" style="height:600px;">
<div id="app-content">
diff --git a/app/popup.html b/app/popup.html
index 3a6709eaf..59e99be43 100644
--- a/app/popup.html
+++ b/app/popup.html
@@ -4,7 +4,8 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=no">
<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>
<body style="width:357px; height:600px;">
<div id="app-content"></div>
diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js
index 4ed3afb6c..b3523cc76 100644
--- a/app/scripts/controllers/preferences.js
+++ b/app/scripts/controllers/preferences.js
@@ -211,7 +211,12 @@ class PreferencesController {
*
*/
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
}
/**
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index b9b44ea80..28537a8eb 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -1723,8 +1723,8 @@ module.exports = class MetamaskController extends EventEmitter {
*/
setCurrentLocale (key, cb) {
try {
- this.preferencesController.setCurrentLocale(key)
- cb(null)
+ const direction = this.preferencesController.setCurrentLocale(key)
+ cb(null, direction)
} catch (err) {
cb(err)
}
diff --git a/gulpfile.js b/gulpfile.js
index 578a64aa2..1969541bf 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -19,6 +19,8 @@ const gulpStylelint = require('gulp-stylelint')
const stylefmt = require('gulp-stylefmt')
const uglify = require('gulp-uglify-es').default
const pify = require('pify')
+const rtlcss = require('gulp-rtlcss')
+const rename = require('gulp-rename')
const gulpMultiProcess = require('gulp-multi-process')
const endOfStream = pify(require('end-of-stream'))
@@ -274,6 +276,10 @@ function createScssBuildTask ({ src, dest, devMode, pattern }) {
.pipe(sourcemaps.write())
.pipe(autoprefixer())
.pipe(gulp.dest(dest))
+ .pipe(rtlcss())
+ .pipe(rename({ suffix: '-rtl' }))
+ .pipe(sourcemaps.write())
+ .pipe(gulp.dest(dest))
}
function buildScss () {
@@ -281,6 +287,9 @@ function createScssBuildTask ({ src, dest, devMode, pattern }) {
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer())
.pipe(gulp.dest(dest))
+ .pipe(rtlcss())
+ .pipe(rename({ suffix: '-rtl' }))
+ .pipe(gulp.dest(dest))
}
}
diff --git a/package.json b/package.json
index 512058239..66d917a5b 100644
--- a/package.json
+++ b/package.json
@@ -218,7 +218,9 @@
"gulp-json-editor": "^2.2.1",
"gulp-livereload": "4.0.0",
"gulp-multi-process": "^1.3.1",
+ "gulp-rename": "^1.4.0",
"gulp-replace": "^0.6.1",
+ "gulp-rtlcss": "^1.4.0",
"gulp-sass": "^4.0.0",
"gulp-sourcemaps": "^2.6.0",
"gulp-stylefmt": "^1.1.0",
diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss b/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss
index be77edbdf..44c721446 100644
--- a/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss
+++ b/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss
@@ -15,6 +15,10 @@
display: flex;
justify-content: center;
align-items: center;
+
+ [dir='rtl'] & img {
+ transform: rotate(180deg);
+ }
}
&__back-button {
diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss b/ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss
index 50953cbe5..a2352a332 100644
--- a/ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss
+++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss
@@ -47,6 +47,8 @@
}
&__input {
+ /*rtl:ignore*/
+ direction: ltr;
border: 1px solid $dusty-gray;
border-radius: 4px;
color: $mid-gray;
@@ -69,6 +71,7 @@
&__input-arrows {
position: absolute;
top: 7px;
+ /*rtl:ignore*/
right: 0px;
width: 17px;
height: 24px;
diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss
index e35b6d594..c107b5400 100644
--- a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss
+++ b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss
@@ -36,6 +36,8 @@
}
&__time-remaining {
+ /*rtl:ignore*/
+ direction: ltr;
color: #313A5E;
font-size: 16px;
@@ -137,6 +139,8 @@
}
&__input {
+ /*rtl:ignore*/
+ direction: ltr;
border: 1px solid $dusty-gray;
border-radius: 4px;
color: $mid-gray;
@@ -159,6 +163,7 @@
&__input-arrows {
position: absolute;
top: 7px;
+ /*rtl:ignore*/
right: 0px;
width: 17px;
height: 24px;
diff --git a/ui/app/components/ui/currency-display/index.scss b/ui/app/components/ui/currency-display/index.scss
index 6d069eb05..074a65df3 100644
--- a/ui/app/components/ui/currency-display/index.scss
+++ b/ui/app/components/ui/currency-display/index.scss
@@ -3,10 +3,11 @@
align-items: center;
&__text {
+ /*rtl:ignore*/
+ direction: ltr;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
-
}
&__suffix {
diff --git a/ui/app/components/ui/editable-label.js b/ui/app/components/ui/editable-label.js
index eb41ec50c..8eb10e174 100644
--- a/ui/app/components/ui/editable-label.js
+++ b/ui/app/components/ui/editable-label.js
@@ -37,6 +37,7 @@ class EditableLabel extends Component {
h('input.large-input.editable-label__input', {
type: 'text',
required: true,
+ dir: 'auto',
value: this.state.value,
onKeyPress: (event) => {
if (event.key === 'Enter') {
diff --git a/ui/app/components/ui/identicon/index.scss b/ui/app/components/ui/identicon/index.scss
index 4c8213f01..6abf57a19 100644
--- a/ui/app/components/ui/identicon/index.scss
+++ b/ui/app/components/ui/identicon/index.scss
@@ -1,4 +1,6 @@
.identicon {
+ /*rtl:ignore*/
+ direction: ltr;
display: flex;
flex-shrink: 0;
align-items: center;
diff --git a/ui/app/components/ui/sender-to-recipient/index.scss b/ui/app/components/ui/sender-to-recipient/index.scss
index b21e4e1bb..641015a81 100644
--- a/ui/app/components/ui/sender-to-recipient/index.scss
+++ b/ui/app/components/ui/sender-to-recipient/index.scss
@@ -50,6 +50,10 @@
display: flex;
align-items: center;
justify-content: center;
+
+ [dir='rtl'] & {
+ transform: rotate(180deg);
+ }
}
&__arrow-circle {
@@ -70,6 +74,19 @@
text-overflow: ellipsis;
white-space: nowrap;
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;
white-space: nowrap;
font-size: .5rem;
+
+ [dir='rtl'] & {
+ /*rtl:ignore*/
+ direction: ltr;
+ /*rtl:ignore*/
+ text-align: right;
+
+ span {
+ display: block;
+ /*rtl:ignore*/
+ direction: rtl;
+ }
+ }
}
&__arrow-container {
display: flex;
justify-content: center;
align-items: center;
+
+ [dir='rtl'] & {
+ transform: rotate(180deg);
+ }
}
}
}
@@ -137,12 +171,29 @@
text-overflow: ellipsis;
white-space: nowrap;
font-size: .6875rem;
+
+ [dir='rtl'] & {
+ /*rtl:ignore*/
+ direction: ltr;
+ /*rtl:ignore*/
+ text-align: right;
+
+ span {
+ display: block;
+ /*rtl:ignore*/
+ direction: rtl;
+ }
+ }
}
&__arrow-container {
display: flex;
justify-content: center;
align-items: center;
+
+ [dir='rtl'] & {
+ transform: rotate(180deg);
+ }
}
}
}
diff --git a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js
index 933f1b007..c8e7a1870 100644
--- a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js
+++ b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js
@@ -66,7 +66,8 @@ export default class SenderToRecipient extends PureComponent {
onHidden={() => this.setState({ senderAddressCopied: false })}
>
<div className="sender-to-recipient__name">
- { addressOnly ? `${t('from')}: ${checksummedSenderAddress}` : senderName }
+ <span>{ addressOnly ? `${t('from')}: ` : '' }</span>
+ { addressOnly ? checksummedSenderAddress : senderName }
</div>
</Tooltip>
)
@@ -112,9 +113,10 @@ export default class SenderToRecipient extends PureComponent {
onHidden={() => this.setState({ recipientAddressCopied: false })}
>
<div className="sender-to-recipient__name">
+ <span>{ addressOnly ? `${t('to')}: ` : '' }</span>
{
addressOnly
- ? `${t('to')}: ${checksummedRecipientAddress}`
+ ? checksummedRecipientAddress
: (recipientNickname || recipientName || this.context.t('newContract'))
}
</div>
diff --git a/ui/app/components/ui/text-field/text-field.component.js b/ui/app/components/ui/text-field/text-field.component.js
index ac7712c65..12a97ee4d 100644
--- a/ui/app/components/ui/text-field/text-field.component.js
+++ b/ui/app/components/ui/text-field/text-field.component.js
@@ -67,7 +67,7 @@ const styles = {
}
const TextField = props => {
- const { error, classes, material, startAdornment, largeLabel, ...textFieldProps } = props
+ const { error, classes, material, startAdornment, largeLabel, dir, ...textFieldProps } = props
return (
<MaterialTextField
@@ -91,6 +91,9 @@ const TextField = props => {
underline: material ? classes.materialUnderline : '',
focused: material ? '' : classes.inputFocused,
},
+ inputProps: {
+ dir,
+ },
}}
{...textFieldProps}
/>
@@ -99,11 +102,13 @@ const TextField = props => {
TextField.defaultProps = {
error: null,
+ dir: 'auto',
}
TextField.propTypes = {
error: PropTypes.string,
classes: PropTypes.object,
+ dir: PropTypes.string,
material: PropTypes.bool,
startAdornment: PropTypes.element,
largeLabel: PropTypes.bool,
diff --git a/ui/app/components/ui/unit-input/unit-input.component.js b/ui/app/components/ui/unit-input/unit-input.component.js
index 9085a0677..01a2e7cf1 100644
--- a/ui/app/components/ui/unit-input/unit-input.component.js
+++ b/ui/app/components/ui/unit-input/unit-input.component.js
@@ -84,6 +84,7 @@ export default class UnitInput extends PureComponent {
<div className="unit-input__input-container">
<input
type="number"
+ dir="ltr"
className={classnames('unit-input__input', { 'unit-input__disabled': maxModeOn })}
value={value}
placeholder={placeholder}
diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss
index 9c0a5cf61..a32930c84 100644
--- a/ui/app/css/itcss/components/modal.scss
+++ b/ui/app/css/itcss/components/modal.scss
@@ -18,6 +18,8 @@
}
.qr-ellip-address, .ellip-address {
+ /*rtl:ignore*/
+ direction: ltr;
width: 247px;
border: none;
font-family: Roboto;
diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss
index ff5f6f6cf..4051bb0b5 100644
--- a/ui/app/css/itcss/components/newui-sections.scss
+++ b/ui/app/css/itcss/components/newui-sections.scss
@@ -57,6 +57,13 @@ $wallet-view-bg: $alabaster;
z-index: 200;
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) {
overflow-y: scroll;
overflow-x: hidden;
@@ -103,6 +110,11 @@ $wallet-view-bg: $alabaster;
box-shadow: rgba(0, 0, 0, .15) 2px 2px 4px;
width: 85%;
height: calc(100% - 56px);
+
+ [dir='rtl'] & {
+ /* rtl:ignore */
+ left: 15%;
+ }
}
// main-container media queries
diff --git a/ui/app/css/itcss/components/sections.scss b/ui/app/css/itcss/components/sections.scss
index feec71c89..2fb9184f1 100644
--- a/ui/app/css/itcss/components/sections.scss
+++ b/ui/app/css/itcss/components/sections.scss
@@ -414,6 +414,8 @@ textarea.twelve-word-phrase {
}
.qr-ellip-address, .ellip-address {
+ /*rtl:ignore*/
+ direction: ltr;
overflow: hidden;
text-overflow: ellipsis;
}
diff --git a/ui/app/css/itcss/components/tab-bar.scss b/ui/app/css/itcss/components/tab-bar.scss
index bb9f8f261..fccba2198 100644
--- a/ui/app/css/itcss/components/tab-bar.scss
+++ b/ui/app/css/itcss/components/tab-bar.scss
@@ -62,6 +62,10 @@
background-size: contain;
background-repeat: no-repeat;
background-position: center;
+
+ [dir='rtl'] & {
+ transform: rotate(180deg);
+ }
}
}
diff --git a/ui/app/helpers/utils/switch-direction.js b/ui/app/helpers/utils/switch-direction.js
new file mode 100644
index 000000000..b0cee933e
--- /dev/null
+++ b/ui/app/helpers/utils/switch-direction.js
@@ -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
diff --git a/ui/app/pages/add-token/token-list/index.scss b/ui/app/pages/add-token/token-list/index.scss
index b7787a18e..bad4ec30f 100644
--- a/ui/app/pages/add-token/token-list/index.scss
+++ b/ui/app/pages/add-token/token-list/index.scss
@@ -58,6 +58,8 @@
}
&__token-name {
+ /*rtl:ignore*/
+ direction: ltr;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
diff --git a/ui/app/pages/first-time-flow/index.scss b/ui/app/pages/first-time-flow/index.scss
index dec80cb60..c674551f4 100644
--- a/ui/app/pages/first-time-flow/index.scss
+++ b/ui/app/pages/first-time-flow/index.scss
@@ -73,6 +73,8 @@
}
&__textarea {
+ /*rtl:ignore*/
+ direction: ltr;
font-size: 1rem;
font-family: Roboto;
height: 190px;
diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss
index f025a503f..279cdbbc5 100644
--- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss
+++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss
@@ -64,6 +64,8 @@
}
&__selected-seed-words {
+ /*rtl:ignore*/
+ direction: ltr;
display: flex;
flex-flow: row wrap;
min-height: 161px;
diff --git a/ui/app/pages/routes/index.js b/ui/app/pages/routes/index.js
index 2f7caf3bf..79438174e 100644
--- a/ui/app/pages/routes/index.js
+++ b/ui/app/pages/routes/index.js
@@ -170,6 +170,7 @@ class Routes extends Component {
const {
isLoading,
alertMessage,
+ textDirection,
loadingMessage,
network,
provider,
@@ -208,6 +209,7 @@ class Routes extends Component {
return (
<div
className={classnames('app', { 'mouse-user-styles': isMouseUser})}
+ dir={textDirection}
onClick={() => setMouseUserState(true)}
onKeyDown={e => {
if (e.keyCode === 9) {
@@ -323,6 +325,7 @@ Routes.propTypes = {
isLoading: PropTypes.bool,
loadingMessage: PropTypes.string,
alertMessage: PropTypes.string,
+ textDirection: PropTypes.string,
network: PropTypes.string,
provider: PropTypes.object,
frequentRpcListDetail: PropTypes.array,
@@ -360,6 +363,7 @@ function mapStateToProps (state) {
sidebar,
alertOpen,
alertMessage,
+ textDirection: state.metamask.textDirection,
isLoading,
loadingMessage,
isUnlocked: state.metamask.isUnlocked,
diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js
index 483d5d344..8f8023fd0 100644
--- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js
+++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js
@@ -155,6 +155,7 @@ export default class EnsInput extends Component {
<input
className="ens-input__wrapper__input"
type="text"
+ dir="auto"
placeholder={t('recipientAddressPlaceholder')}
onChange={this.onChange}
onPaste={this.onPaste}
diff --git a/ui/app/pages/send/send.scss b/ui/app/pages/send/send.scss
index 9b95f1b39..a0c36bdac 100644
--- a/ui/app/pages/send/send.scss
+++ b/ui/app/pages/send/send.scss
@@ -60,6 +60,10 @@
width: 18px;
height: 18px;
margin-right: .5rem;
+
+ [dir='rtl'] & {
+ transform: rotate(180deg);
+ }
}
}
diff --git a/ui/app/pages/send/to-autocomplete/to-autocomplete.js b/ui/app/pages/send/to-autocomplete/to-autocomplete.js
index 8ad579958..71c69b5fb 100644
--- a/ui/app/pages/send/to-autocomplete/to-autocomplete.js
+++ b/ui/app/pages/send/to-autocomplete/to-autocomplete.js
@@ -99,6 +99,7 @@ ToAutoComplete.prototype.render = function () {
h(`input.send-v2__to-autocomplete__input${qrScanner ? '.with-qr' : ''}`, {
placeholder: this.context.t('recipientAddress'),
className: inError ? `send-v2__error-border` : '',
+ dir: 'auto',
value: to,
onChange: event => onChange(event.target.value),
onFocus: event => this.handleInputEvent(event),
diff --git a/ui/app/pages/settings/contact-list-tab/index.scss b/ui/app/pages/settings/contact-list-tab/index.scss
index c7e99095f..aad50c419 100644
--- a/ui/app/pages/settings/contact-list-tab/index.scss
+++ b/ui/app/pages/settings/contact-list-tab/index.scss
@@ -197,6 +197,10 @@
width: 30px;
opacity: .5;
background-repeat: no-repeat;
+
+ [dir='rtl'] & {
+ transform: rotate(180deg);
+ }
}
}
}
diff --git a/ui/app/pages/settings/index.scss b/ui/app/pages/settings/index.scss
index 041d12f72..550fd1e7d 100644
--- a/ui/app/pages/settings/index.scss
+++ b/ui/app/pages/settings/index.scss
@@ -97,6 +97,10 @@
background-position: center;
margin-right: 16px;
cursor: pointer;
+
+ [dir='rtl'] & {
+ transform: rotate(180deg);
+ }
}
}
@@ -244,4 +248,12 @@
}
}
}
+
+ .toggle-button {
+ /*rtl:ignore*/
+ direction: ltr;
+ [dir='rtl'] & {
+ justify-content: flex-end;
+ }
+ }
}
diff --git a/ui/app/pages/settings/networks-tab/index.scss b/ui/app/pages/settings/networks-tab/index.scss
index bf83c7a14..b9f4245f9 100644
--- a/ui/app/pages/settings/networks-tab/index.scss
+++ b/ui/app/pages/settings/networks-tab/index.scss
@@ -38,6 +38,10 @@
cursor: pointer;
position: absolute;
margin-left: 10px;
+
+ [dir='rtl'] & {
+ transform: rotate(180deg);
+ }
}
}
@@ -190,6 +194,10 @@
position: absolute;
width: 24px;
height: 24px;
+
+ [dir='rtl'] & {
+ transform: rotate(180deg);
+ }
}
}
diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js
index 2b0b54c60..87b01a74c 100644
--- a/ui/app/store/actions.js
+++ b/ui/app/store/actions.js
@@ -10,6 +10,7 @@ const ethUtil = require('ethereumjs-util')
const { fetchLocale } = require('../helpers/utils/i18n-helper')
const { getMethodDataAsync } = require('../helpers/utils/transactions.util')
const { fetchSymbolAndDecimals } = require('../helpers/utils/token-util')
+import switchDirection from '../helpers/utils/switch-direction'
const log = require('loglevel')
const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../../app/scripts/lib/enums')
const { hasUnconfirmedTransactions } = require('../helpers/utils/confirm-tx.util')
@@ -2597,11 +2598,13 @@ function updateCurrentLocale (key) {
return fetchLocale(key)
.then((localeMessages) => {
log.debug(`background.setCurrentLocale`)
- background.setCurrentLocale(key, (err) => {
- dispatch(actions.hideLoadingIndication())
+ background.setCurrentLocale(key, (err, textDirection) => {
if (err) {
+ dispatch(actions.hideLoadingIndication())
return dispatch(actions.displayWarning(err.message))
}
+ switchDirection(textDirection)
+ dispatch(actions.hideLoadingIndication())
dispatch(actions.setCurrentLocale(key))
dispatch(actions.setLocaleMessages(localeMessages))
})
diff --git a/ui/index.html b/ui/index.html
index 9dfaefbb3..38515e09b 100644
--- a/ui/index.html
+++ b/ui/index.html
@@ -12,6 +12,7 @@
<!-- design reference -->
<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">
<img id="design-img" src="./design/metamask_wfs_jan_13.png">
</div>
diff --git a/ui/index.js b/ui/index.js
index db9292761..0f15594d2 100644
--- a/ui/index.js
+++ b/ui/index.js
@@ -5,6 +5,7 @@ const actions = require('./app/store/actions')
const configureStore = require('./app/store/store')
const txHelper = require('./lib/tx-helper')
const { fetchLocale } = require('./app/helpers/utils/i18n-helper')
+import switchDirection from './app/helpers/utils/switch-direction'
const log = require('loglevel')
module.exports = launchMetamaskUi
@@ -33,6 +34,10 @@ async function startApp (metamaskState, backgroundConnection, opts) {
: {}
const enLocaleMessages = await fetchLocale('en')
+ if (metamaskState.textDirection === 'rtl') {
+ await switchDirection('rtl')
+ }
+
const store = configureStore({
activeTab: opts.activeTab,
diff --git a/yarn.lock b/yarn.lock
index 7ec582150..9ec8f2dfd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5728,6 +5728,11 @@ colors@^1.1.0, colors@^1.1.2:
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
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:
version "1.5.4"
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:
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:
version "2.19.0"
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"
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:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476"
@@ -11039,6 +11057,11 @@ gulp-multi-process@^1.3.1:
dependencies:
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:
version "0.6.1"
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"
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:
version "4.0.1"
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"
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:
version "7.0.17"
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"
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"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
@@ -18883,6 +18925,17 @@ rtcpeerconnection-shim@^1.2.10:
dependencies:
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:
version "0.1.0"
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"
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"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
@@ -21276,6 +21329,14 @@ through2@^1.1.1:
readable-stream ">=1.1.13-1 <1.2.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:
version "0.2.3"
resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f"