mirror of
https://github.com/zulip/zulip.git
synced 2025-11-04 14:03:30 +00:00
hotkeys: Replace C with x for composing PM.
Pressing the 'x' key can now be used to compose a PM. Pressing the 'C' key displays a modal that shows a deprecation notice. Fixes #6548.
This commit is contained in:
committed by
Tim Abbott
parent
af004fa6f5
commit
1227857de6
@@ -150,7 +150,7 @@ populated and where the focus is placed.
|
|||||||
- use R to reply to the author of a PM
|
- use R to reply to the author of a PM
|
||||||
- use R to reply to the author of a PM stream
|
- use R to reply to the author of a PM stream
|
||||||
- use c to compose a stream message
|
- use c to compose a stream message
|
||||||
- use C to compose a new PM
|
- use x to compose a new PM
|
||||||
|
|
||||||
- Buttons
|
- Buttons
|
||||||
- Narrow to a stream and click on "New topic"
|
- Narrow to a stream and click on "New topic"
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ exports.then_send_message = function (type, params) {
|
|||||||
if (type === "stream") {
|
if (type === "stream") {
|
||||||
casper.page.sendEvent('keypress', "c");
|
casper.page.sendEvent('keypress', "c");
|
||||||
} else if (type === "private") {
|
} else if (type === "private") {
|
||||||
casper.page.sendEvent('keypress', "C");
|
casper.page.sendEvent('keypress', "x");
|
||||||
} else {
|
} else {
|
||||||
casper.test.assertTrue(false, "send_message got valid message type");
|
casper.test.assertTrue(false, "send_message got valid message type");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ casper.then(function () {
|
|||||||
casper.test.assertVisible('#stream-message', 'Stream input box visible');
|
casper.test.assertVisible('#stream-message', 'Stream input box visible');
|
||||||
common.check_form('#send_message_form', {stream: '', subject: ''}, "Stream empty on new compose");
|
common.check_form('#send_message_form', {stream: '', subject: ''}, "Stream empty on new compose");
|
||||||
casper.click('body');
|
casper.click('body');
|
||||||
casper.page.sendEvent('keypress', "C");
|
casper.page.sendEvent('keypress', "x");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ casper.then(function () {
|
|||||||
casper.then(function () {
|
casper.then(function () {
|
||||||
casper.waitWhileVisible('#stream-message', function () {
|
casper.waitWhileVisible('#stream-message', function () {
|
||||||
casper.test.assertNotVisible('#stream-message', 'Close stream compose box');
|
casper.test.assertNotVisible('#stream-message', 'Close stream compose box');
|
||||||
casper.page.sendEvent('keypress', "C");
|
casper.page.sendEvent('keypress', "x");
|
||||||
casper.click('body');
|
casper.click('body');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ casper.then(function () {
|
|||||||
casper.then(function () {
|
casper.then(function () {
|
||||||
casper.test.info('Creating Private Message Draft');
|
casper.test.info('Creating Private Message Draft');
|
||||||
casper.click('body');
|
casper.click('body');
|
||||||
casper.page.sendEvent('keypress', "C");
|
casper.page.sendEvent('keypress', "x");
|
||||||
casper.waitUntilVisible('#private-message', function () {
|
casper.waitUntilVisible('#private-message', function () {
|
||||||
casper.fill('form#send_message_form', {
|
casper.fill('form#send_message_form', {
|
||||||
content: 'Test Private Message',
|
content: 'Test Private Message',
|
||||||
@@ -171,7 +171,7 @@ casper.then(function () {
|
|||||||
casper.click('#draft_overlay .exit');
|
casper.click('#draft_overlay .exit');
|
||||||
waitWhileDraftsVisible(function () {
|
waitWhileDraftsVisible(function () {
|
||||||
casper.click('body');
|
casper.click('body');
|
||||||
casper.page.sendEvent('keypress', "C");
|
casper.page.sendEvent('keypress', "x");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ function stubbing(func_name_to_stub, test_function) {
|
|||||||
|
|
||||||
// Unmapped keys should immediately return false, without
|
// Unmapped keys should immediately return false, without
|
||||||
// calling any functions outside of hotkey.js.
|
// calling any functions outside of hotkey.js.
|
||||||
assert_unmapped('abefhlmotxyz');
|
assert_unmapped('abefhlmotyz');
|
||||||
assert_unmapped('BEFHILNOQTUWXYZ');
|
assert_unmapped('BEFHILNOQTUWXYZ');
|
||||||
|
|
||||||
// We have to skip some checks due to the way the code is
|
// We have to skip some checks due to the way the code is
|
||||||
@@ -224,7 +224,7 @@ function stubbing(func_name_to_stub, test_function) {
|
|||||||
assert_mapping('D', 'narrow.stream_cycle_forward');
|
assert_mapping('D', 'narrow.stream_cycle_forward');
|
||||||
|
|
||||||
assert_mapping('c', 'compose_actions.start');
|
assert_mapping('c', 'compose_actions.start');
|
||||||
assert_mapping('C', 'compose_actions.start');
|
assert_mapping('x', 'compose_actions.start');
|
||||||
assert_mapping('P', 'narrow.by');
|
assert_mapping('P', 'narrow.by');
|
||||||
assert_mapping('g', 'gear_menu.open');
|
assert_mapping('g', 'gear_menu.open');
|
||||||
|
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ exports.start = function (msg_type, opts) {
|
|||||||
exports.expand_compose_box();
|
exports.expand_compose_box();
|
||||||
|
|
||||||
opts = fill_in_opts_from_current_narrowed_view(msg_type, opts);
|
opts = fill_in_opts_from_current_narrowed_view(msg_type, opts);
|
||||||
// If we are invoked by a compose hotkey (c or C), do not assume that we know
|
// If we are invoked by a compose hotkey (c or x), do not assume that we know
|
||||||
// what the message's topic or PM recipient should be.
|
// what the message's topic or PM recipient should be.
|
||||||
if ((opts.trigger === "compose_hotkey") || (opts.trigger === "new topic button")) {
|
if ((opts.trigger === "compose_hotkey") || (opts.trigger === "new topic button")) {
|
||||||
opts.subject = '';
|
opts.subject = '';
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ var keypress_mappings = {
|
|||||||
63: {name: 'show_shortcuts', message_view_only: false}, // '?'
|
63: {name: 'show_shortcuts', message_view_only: false}, // '?'
|
||||||
64: {name: 'compose_reply_with_mention', message_view_only: true}, // '@'
|
64: {name: 'compose_reply_with_mention', message_view_only: true}, // '@'
|
||||||
65: {name: 'stream_cycle_backward', message_view_only: true}, // 'A'
|
65: {name: 'stream_cycle_backward', message_view_only: true}, // 'A'
|
||||||
67: {name: 'compose_private_message', message_view_only: true}, // 'C'
|
67: {name: 'C_deprecated', message_view_only: true}, // 'C'
|
||||||
68: {name: 'stream_cycle_forward', message_view_only: true}, // 'D'
|
68: {name: 'stream_cycle_forward', message_view_only: true}, // 'D'
|
||||||
71: {name: 'G_end', message_view_only: true}, // 'G'
|
71: {name: 'G_end', message_view_only: true}, // 'G'
|
||||||
74: {name: 'vim_page_down', message_view_only: true}, // 'J'
|
74: {name: 'vim_page_down', message_view_only: true}, // 'J'
|
||||||
@@ -102,6 +102,7 @@ var keypress_mappings = {
|
|||||||
117: {name: 'show_sender_info', message_view_only: true}, // 'u'
|
117: {name: 'show_sender_info', message_view_only: true}, // 'u'
|
||||||
118: {name: 'show_lightbox', message_view_only: true}, // 'v'
|
118: {name: 'show_lightbox', message_view_only: true}, // 'v'
|
||||||
119: {name: 'query_users', message_view_only: false}, // 'w'
|
119: {name: 'query_users', message_view_only: false}, // 'w'
|
||||||
|
120: {name: 'compose_private_message', message_view_only: true}, // 'x'
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.get_keydown_hotkey = function (e) {
|
exports.get_keydown_hotkey = function (e) {
|
||||||
@@ -644,6 +645,9 @@ exports.process_hotkey = function (e, hotkey) {
|
|||||||
// but that is handled in process_enter_key().
|
// but that is handled in process_enter_key().
|
||||||
compose_actions.respond_to_message({trigger: 'hotkey'});
|
compose_actions.respond_to_message({trigger: 'hotkey'});
|
||||||
return true;
|
return true;
|
||||||
|
case 'C_deprecated':
|
||||||
|
ui.maybe_show_deprecation_notice('C');
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_msg_list.empty()) {
|
if (current_msg_list.empty()) {
|
||||||
|
|||||||
@@ -122,6 +122,27 @@ exports.show_failed_message_success = function (message_id) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.maybe_show_deprecation_notice = function (key) {
|
||||||
|
var message;
|
||||||
|
if (key === 'C') {
|
||||||
|
message = i18n.t('We\'ve replaced the "C" hotkey with "x" to make this common shortcut easier to trigger.');
|
||||||
|
} else {
|
||||||
|
// should never get here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var shown_deprecation_notices = JSON.parse(localStorage.getItem('shown_deprecation_notices'));
|
||||||
|
if (shown_deprecation_notices === null) {
|
||||||
|
shown_deprecation_notices = [];
|
||||||
|
}
|
||||||
|
if (shown_deprecation_notices.indexOf(key) === -1) {
|
||||||
|
$('#deprecation-notice-modal').modal('show');
|
||||||
|
$('#deprecation-notice-message').text(message);
|
||||||
|
shown_deprecation_notices.push(key);
|
||||||
|
localStorage.setItem('shown_deprecation_notices', JSON.stringify(shown_deprecation_notices));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* EXPERIMENTS */
|
/* EXPERIMENTS */
|
||||||
|
|
||||||
/* This method allows an advanced user to use the console
|
/* This method allows an advanced user to use the console
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<span class="new_message_button">
|
<span class="new_message_button">
|
||||||
<button type="button" class="button small rounded compose_private_button"
|
<button type="button" class="button small rounded compose_private_button"
|
||||||
id="left_bar_compose_private_button_big"
|
id="left_bar_compose_private_button_big"
|
||||||
title="{{ _('New private message') }} (C)">
|
title="{{ _('New private message') }} (x)">
|
||||||
<span class="compose_private_button_label">{{ _('New private message') }}</span>
|
<span class="compose_private_button_label">{{ _('New private message') }}</span>
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
16
templates/zerver/deprecation_notice.html
Normal file
16
templates/zerver/deprecation_notice.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<div class="modal hide modal-bg new-style" id="deprecation-notice-modal" role="dialog"
|
||||||
|
aria-labelledby="deprecation-notice-label" aria-hidden="true">
|
||||||
|
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="{{ _('Close') }}"><span aria-hidden="true">×</span></button>
|
||||||
|
<h3 id="deprecation-notice-label">{{ _('Deprecation notice') }}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<p id="deprecation-notice-message"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="button rounded" data-dismiss="modal">{{ _("Got it") }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -20,7 +20,7 @@ below, and add more to your repertoire as needed.
|
|||||||
|
|
||||||
* **New stream message**: `c` — Start a new topic in the current stream.
|
* **New stream message**: `c` — Start a new topic in the current stream.
|
||||||
|
|
||||||
* **New private message**: `C`
|
* **New private message**: `x`
|
||||||
|
|
||||||
* **Cancel compose**: `Esc` or `Ctrl + [` — Close the compose box and save
|
* **Cancel compose**: `Esc` or `Ctrl + [` — Close the compose box and save
|
||||||
the unsent message as a draft.
|
the unsent message as a draft.
|
||||||
@@ -93,7 +93,7 @@ below, and add more to your repertoire as needed.
|
|||||||
|
|
||||||
* **New stream message**: `c` — For starting a new topic in a stream.
|
* **New stream message**: `c` — For starting a new topic in a stream.
|
||||||
|
|
||||||
* **New private message**: `C`
|
* **New private message**: `x`
|
||||||
|
|
||||||
### In the compose box
|
### In the compose box
|
||||||
|
|
||||||
|
|||||||
@@ -153,6 +153,7 @@
|
|||||||
{% include "zerver/invite_user.html" %}
|
{% include "zerver/invite_user.html" %}
|
||||||
{% include "zerver/bankruptcy.html" %}
|
{% include "zerver/bankruptcy.html" %}
|
||||||
{% include "zerver/logout.html" %}
|
{% include "zerver/logout.html" %}
|
||||||
|
{% include "zerver/deprecation_notice.html" %}
|
||||||
<div class='notifications top-right'></div>
|
<div class='notifications top-right'></div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<td class="definition">{% trans %}New stream message{% endtrans %}</td>
|
<td class="definition">{% trans %}New stream message{% endtrans %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="hotkey">C</td>
|
<td class="hotkey">x</td>
|
||||||
<td class="definition">{% trans %}New private message{% endtrans %}</td>
|
<td class="definition">{% trans %}New private message{% endtrans %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
<td class="definition">{% trans %}New stream message{% endtrans %}</td>
|
<td class="definition">{% trans %}New stream message{% endtrans %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="hotkey">C</td>
|
<td class="hotkey">x</td>
|
||||||
<td class="definition">{% trans %}New private message{% endtrans %}</td>
|
<td class="definition">{% trans %}New private message{% endtrans %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ class TemplateTestCase(ZulipTestCase):
|
|||||||
'zerver/api_content.json',
|
'zerver/api_content.json',
|
||||||
'zerver/handlebars_compilation_failed.html',
|
'zerver/handlebars_compilation_failed.html',
|
||||||
'zerver/portico-header.html',
|
'zerver/portico-header.html',
|
||||||
|
'zerver/deprecation_notice.html',
|
||||||
]
|
]
|
||||||
|
|
||||||
integrations_regexp = re.compile('zerver/integrations/.*.html')
|
integrations_regexp = re.compile('zerver/integrations/.*.html')
|
||||||
|
|||||||
Reference in New Issue
Block a user