diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 729cc1181..71d5f0b07 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -1920,6 +1920,11 @@
"description":
"Button action that the user can click to view their unique seed"
},
+ "showQRCode": {
+ "message": "Show QR code",
+ "description":
+ "Button action that the user can click to view their QR code"
+ },
"seedViewTitle": {
"message":
diff --git a/background.html b/background.html
index a62c7dd4c..35f2b6686 100644
--- a/background.html
+++ b/background.html
@@ -281,6 +281,13 @@
+
+
diff --git a/js/background.js b/js/background.js
index 799d8f8f3..7f62f551b 100644
--- a/js/background.js
+++ b/js/background.js
@@ -757,6 +757,13 @@
}
});
+ Whisper.events.on('showQRDialog', async () => {
+ if (appView) {
+ const ourNumber = textsecure.storage.user.getNumber();
+ appView.showQRDialog(ourNumber);
+ }
+ });
+
Whisper.events.on('calculatingPoW', ({ pubKey, timestamp }) => {
try {
const conversation = ConversationController.get(pubKey);
diff --git a/js/views/app_view.js b/js/views/app_view.js
index f9f306789..31235bf9f 100644
--- a/js/views/app_view.js
+++ b/js/views/app_view.js
@@ -196,5 +196,9 @@
const dialog = new Whisper.SeedDialogView({ seed });
this.el.append(dialog.el);
},
+ showQRDialog(string) {
+ const dialog = new Whisper.QRDialogView({ string });
+ this.el.append(dialog.el);
+ },
});
})();
diff --git a/js/views/qr_dialog_view.js b/js/views/qr_dialog_view.js
new file mode 100644
index 000000000..5a710fe7f
--- /dev/null
+++ b/js/views/qr_dialog_view.js
@@ -0,0 +1,49 @@
+/* global Whisper, i18n, QRCode */
+
+/* eslint-disable more/no-then */
+
+// eslint-disable-next-line func-names
+(function() {
+ 'use strict';
+
+ window.Whisper = window.Whisper || {};
+
+ Whisper.QRDialogView = Whisper.View.extend({
+ templateName: 'qr-code-template',
+ className: 'loki-dialog qr-dialog modal',
+ initialize(options = {}) {
+ this.okText = options.okText || i18n('ok');
+ this.render();
+ this.$('.qr-dialog').bind('keyup', event =>
+ this.onKeyup(event)
+ );
+
+ if (options.string) {
+ this.qr = new QRCode(this.$('#qr')[0]).makeCode(options.string);
+ this.$('#qr').addClass('ready');
+ }
+ },
+ events: {
+ 'click .ok': 'close',
+ },
+ render_attributes() {
+ return {
+ ok: this.okText,
+ };
+ },
+ close() {
+ this.remove();
+ },
+ onKeyup(event) {
+ switch (event.key) {
+ case 'Enter':
+ case 'Escape':
+ case 'Esc':
+ this.close();
+ break;
+ default:
+ break;
+ }
+ },
+ });
+})();
diff --git a/stylesheets/_conversation.scss b/stylesheets/_conversation.scss
index 8495b38f5..8ea4f05b4 100644
--- a/stylesheets/_conversation.scss
+++ b/stylesheets/_conversation.scss
@@ -383,6 +383,7 @@
border: 1px solid $color-loki-green;
color: white;
outline: none;
+ user-select: none;
&:hover,
&:disabled {
diff --git a/stylesheets/_global.scss b/stylesheets/_global.scss
index a928ad882..f275fa9f2 100644
--- a/stylesheets/_global.scss
+++ b/stylesheets/_global.scss
@@ -860,3 +860,18 @@ $loading-height: 16px;
.inbox {
position: relative;
}
+
+.qr-dialog {
+
+ .content {
+ width: 300px !important;
+ max-width: none !important;
+ min-width: auto !important;
+ }
+
+ #qr {
+ display: flex;
+ justify-content: center;
+ margin-bottom: 1em;
+ }
+}
diff --git a/test/index.html b/test/index.html
index 61087bb86..5ebafa95f 100644
--- a/test/index.html
+++ b/test/index.html
@@ -567,6 +567,7 @@
+
diff --git a/ts/components/MainHeader.tsx b/ts/components/MainHeader.tsx
index 946077894..90a9b543f 100644
--- a/ts/components/MainHeader.tsx
+++ b/ts/components/MainHeader.tsx
@@ -327,6 +327,13 @@ export class MainHeader extends React.Component {
trigger('showSeedDialog');
},
},
+ {
+ id: 'showQRCode',
+ name: i18n('showQRCode'),
+ onClick: () => {
+ trigger('showQRDialog');
+ },
+ }
];
const passItem = (type: string) => ({