diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index d6e7e7e5b..14915f324 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -781,6 +781,9 @@
"cancel": {
"message": "Cancel"
},
+ "clear": {
+ "message": "Clear"
+ },
"failedToSend": {
"message":
"Failed to send to some recipients. Check your network connection."
diff --git a/background.html b/background.html
index e7463fcb5..40dc5bb73 100644
--- a/background.html
+++ b/background.html
@@ -150,6 +150,20 @@
0:00
+
+
diff --git a/js/background.js b/js/background.js
index 71e5935ee..03f49ba4a 100644
--- a/js/background.js
+++ b/js/background.js
@@ -568,6 +568,12 @@
}
});
+ Whisper.events.on('showNicknameDialog', options => {
+ if (appView) {
+ appView.showNicknameDialog(options);
+ }
+ });
+
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 1db6314e3..acd6a8329 100644
--- a/js/views/app_view.js
+++ b/js/views/app_view.js
@@ -178,5 +178,15 @@
});
}
},
+ showNicknameDialog({ pubKey, title, nickname, onOk, onCancel }) {
+ const _title = title || `Change nickname for ${pubKey}`;
+ const dialog = new Whisper.NicknameDialogView({
+ title: _title,
+ name: nickname,
+ resolve: onOk,
+ reject: onCancel,
+ });
+ this.el.append(dialog.el);
+ },
});
})();
diff --git a/js/views/nickname_dialog_view.js b/js/views/nickname_dialog_view.js
new file mode 100644
index 000000000..8d4d092eb
--- /dev/null
+++ b/js/views/nickname_dialog_view.js
@@ -0,0 +1,101 @@
+/* global Whisper, i18n, _ */
+
+// eslint-disable-next-line func-names
+(function() {
+ 'use strict';
+
+ window.Whisper = window.Whisper || {};
+
+ Whisper.NicknameDialogView = Whisper.View.extend({
+ className: 'nickname-dialog modal',
+ templateName: 'nickname-dialog',
+ initialize(options) {
+ this.message = options.message;
+ this.name = options.name;
+
+ this.resolve = options.resolve;
+ this.okText = options.okText || i18n('ok');
+
+ this.reject = options.reject;
+ this.cancelText = options.cancelText || i18n('cancel');
+
+ this.clear = options.clear;
+ this.clearText = options.clearText || i18n('clear');
+
+ this.title = options.title;
+
+ this.render();
+
+ this.$input = this.$('input');
+ this.validateNickname();
+ },
+ events: {
+ keyup: 'onKeyup',
+ 'click .ok': 'ok',
+ 'click .cancel': 'cancel',
+ 'click .clear': 'clear',
+ change: 'validateNickname',
+ },
+ isValidNickname(name) {
+ return (name || '').length < 20;
+ },
+ validateNickname() {
+ const nickname = this.$input.val();
+
+ if (_.isEmpty(nickname)) {
+ this.$('.clear').hide();
+ } else {
+ this.$('.clear').show();
+ }
+
+ if (this.isValidNickname(nickname)) {
+ this.$('.content').removeClass('invalid');
+ this.$('.content').addClass('valid');
+ this.$('.ok').show();
+ } else {
+ this.$('.content').removeClass('valid');
+ this.$('.ok').hide();
+ }
+ },
+ render_attributes() {
+ return {
+ name: this.name,
+ message: this.message,
+ showCancel: !this.hideCancel,
+ cancel: this.cancelText,
+ ok: this.okText,
+ clear: this.clearText,
+ title: this.title,
+ };
+ },
+ ok() {
+ const nickname = this.$input.val();
+ if (!this.isValidNickname(nickname)) return;
+
+ this.remove();
+ if (this.resolve) {
+ this.resolve(nickname);
+ }
+ },
+ cancel() {
+ this.remove();
+ if (this.reject) {
+ this.reject();
+ }
+ },
+ clear() {
+ this.$input.val('').trigger('change');
+ },
+ onKeyup(event) {
+ if (event.key === 'Escape' || event.key === 'Esc') {
+ this.cancel();
+ return;
+ }
+
+ this.validateNickname();
+ },
+ focusCancel() {
+ this.$('.cancel').focus();
+ },
+ });
+})();
diff --git a/stylesheets/_conversation.scss b/stylesheets/_conversation.scss
index 3d8376aa9..ca468bd9b 100644
--- a/stylesheets/_conversation.scss
+++ b/stylesheets/_conversation.scss
@@ -351,6 +351,57 @@
}
}
+
+.nickname-dialog {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ .content {
+ max-width: 75%;
+ padding: 1em;
+ background: white;
+ border-radius: $border-radius;
+ overflow: auto;
+ box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, 0.3);
+
+ .buttons {
+ margin-top: 10px;
+
+ button {
+ float: right;
+ margin-left: 10px;
+ background-color: $grey_l;
+ border-radius: $border-radius;
+ padding: 5px 8px;
+ border: 1px solid $grey_l2;
+
+ &:hover {
+ background-color: $grey_l2;
+ border-color: $grey_l3;
+ }
+ }
+ }
+
+ input {
+ width: 100%;
+ padding: 8px;
+ margin-bottom: 4px;
+ }
+
+ h4 {
+ white-space: -moz-pre-wrap; /* Mozilla */
+ white-space: -hp-pre-wrap; /* HP printers */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: pre-wrap; /* CSS 2.1 */
+ white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */
+ word-wrap: break-word; /* IE */
+ word-break: break-all;
+ }
+ }
+}
+
.permissions-popup,
.debug-log-window {
.modal {
diff --git a/test/index.html b/test/index.html
index e03ce96cf..05d46c1c6 100644
--- a/test/index.html
+++ b/test/index.html
@@ -127,6 +127,17 @@
0:00
+
+