Add ctrl+enter shortcut for conversations
This commit is contained in:
parent
1fc31cc313
commit
a22127bfb1
7 changed files with 120 additions and 47 deletions
|
|
@ -23,6 +23,7 @@
|
||||||
* Hide post title of limited post in comment notification email [#5843](https://github.com/diaspora/diaspora/pull/5843)
|
* Hide post title of limited post in comment notification email [#5843](https://github.com/diaspora/diaspora/pull/5843)
|
||||||
* More and better environment checks in script/server [#5891](https://github.com/diaspora/diaspora/pull/5891)
|
* More and better environment checks in script/server [#5891](https://github.com/diaspora/diaspora/pull/5891)
|
||||||
* Enable aspect sorting again [#5559](https://github.com/diaspora/diaspora/pull/5559)
|
* Enable aspect sorting again [#5559](https://github.com/diaspora/diaspora/pull/5559)
|
||||||
|
* Submit messages in conversations with Ctrl+Enter [#5910](https://github.com/diaspora/diaspora/pull/5910)
|
||||||
|
|
||||||
# 0.5.0.0
|
# 0.5.0.0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,14 @@
|
||||||
|
|
||||||
app.views.ConversationsForm = Backbone.View.extend({
|
app.views.ConversationsForm = Backbone.View.extend({
|
||||||
|
|
||||||
|
events: {
|
||||||
|
"keydown textarea#conversation_text" : "keyDown",
|
||||||
|
},
|
||||||
|
|
||||||
initialize: function(opts) {
|
initialize: function(opts) {
|
||||||
this.contacts = _.has(opts, 'contacts') ? opts.contacts : null;
|
this.contacts = _.has(opts, "contacts") ? opts.contacts : null;
|
||||||
this.prefill = [];
|
this.prefill = [];
|
||||||
if (_.has(opts, 'prefillName') && _.has(opts, 'prefillValue')) {
|
if (_.has(opts, "prefillName") && _.has(opts, "prefillValue")) {
|
||||||
this.prefill = [{name : opts.prefillName,
|
this.prefill = [{name : opts.prefillName,
|
||||||
value : opts.prefillValue}];
|
value : opts.prefillValue}];
|
||||||
}
|
}
|
||||||
|
|
@ -22,9 +26,15 @@ app.views.ConversationsForm = Backbone.View.extend({
|
||||||
minChars: 1,
|
minChars: 1,
|
||||||
keyDelay: 0,
|
keyDelay: 0,
|
||||||
startText: '',
|
startText: '',
|
||||||
emptyText: Diaspora.I18n.t('no_results'),
|
emptyText: Diaspora.I18n.t("no_results"),
|
||||||
preFill: this.prefill
|
preFill: this.prefill
|
||||||
}).focus();
|
}).focus();
|
||||||
|
},
|
||||||
|
|
||||||
|
keyDown : function(evt) {
|
||||||
|
if( evt.keyCode === 13 && evt.ctrlKey ) {
|
||||||
|
$(evt.target).parents("form").submit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|
|
||||||
|
|
@ -5,44 +5,54 @@ app.views.Conversations = Backbone.View.extend({
|
||||||
el: "#conversations_container",
|
el: "#conversations_container",
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
|
"keydown textarea#message_text" : "keyDown",
|
||||||
"conversation:loaded" : "setupConversation"
|
"conversation:loaded" : "setupConversation"
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
if($('#conversation_new:visible').length > 0) {
|
if($("#conversation_new:visible").length > 0) {
|
||||||
new app.views.ConversationsForm({contacts: gon.contacts});
|
new app.views.ConversationsForm({
|
||||||
|
el: $("#conversation_new"),
|
||||||
|
contacts: gon.contacts
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.setupConversation();
|
this.setupConversation();
|
||||||
},
|
},
|
||||||
|
|
||||||
setupConversation: function() {
|
setupConversation: function() {
|
||||||
app.helpers.timeago($(this.el));
|
app.helpers.timeago($(this.el));
|
||||||
$('.control-icons a').tooltip({placement: 'bottom'});
|
$(".control-icons a").tooltip({placement: "bottom"});
|
||||||
|
|
||||||
var conv = $('.conversation-wrapper .stream_element.selected'),
|
var conv = $(".conversation-wrapper .stream_element.selected"),
|
||||||
cBadge = $('#conversations_badge .badge_count');
|
cBadge = $("#conversations_badge .badge_count");
|
||||||
|
|
||||||
if(conv.hasClass('unread') ){
|
if(conv.hasClass("unread") ){
|
||||||
var unreadCount = parseInt(conv.find('.unread_message_count').text(), 10);
|
var unreadCount = parseInt(conv.find(".unread_message_count").text(), 10);
|
||||||
|
|
||||||
if(cBadge.text() !== '') {
|
if(cBadge.text() !== "") {
|
||||||
cBadge.text().replace(/\d+/, function(num){
|
cBadge.text().replace(/\d+/, function(num){
|
||||||
num = parseInt(num, 10) - unreadCount;
|
num = parseInt(num, 10) - unreadCount;
|
||||||
if(num > 0) {
|
if(num > 0) {
|
||||||
cBadge.text(num);
|
cBadge.text(num);
|
||||||
} else {
|
} else {
|
||||||
cBadge.text(0).addClass('hidden');
|
cBadge.text(0).addClass("hidden");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
conv.removeClass('unread');
|
conv.removeClass("unread");
|
||||||
conv.find('.unread_message_count').remove();
|
conv.find(".unread_message_count").remove();
|
||||||
|
|
||||||
var pos = $('#first_unread').offset().top - 50;
|
var pos = $("#first_unread").offset().top - 50;
|
||||||
$("html").animate({scrollTop:pos});
|
$("html").animate({scrollTop:pos});
|
||||||
} else {
|
} else {
|
||||||
$("html").animate({scrollTop:0});
|
$("html").animate({scrollTop:0});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
keyDown : function(evt) {
|
||||||
|
if( evt.keyCode === 13 && evt.ctrlKey ) {
|
||||||
|
$(evt.target).parents("form").submit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|
|
||||||
|
|
@ -24,3 +24,15 @@ Feature: private conversations
|
||||||
And I should have 1 email delivery
|
And I should have 1 email delivery
|
||||||
When I reply with "hey, how you doing?"
|
When I reply with "hey, how you doing?"
|
||||||
Then I should see "hey, how you doing?" within ".stream_container"
|
Then I should see "hey, how you doing?" within ".stream_container"
|
||||||
|
|
||||||
|
Scenario: send a message using keyboard shortcuts
|
||||||
|
Given I send a message with subject "Greetings" and text "hello, alice!" to "Alice Awesome" using keyboard shortcuts
|
||||||
|
Then I should see "Greetings" within "#conversation_inbox"
|
||||||
|
And I should see "Greetings" within "#conversation_show"
|
||||||
|
And "Alice Awesome" should be part of active conversation
|
||||||
|
And I should see "hello, alice!" within ".stream_container"
|
||||||
|
When I reply with "hey, how you doing?" using keyboard shortcuts
|
||||||
|
Then I should see "hey, how you doing?" within ".stream_container"
|
||||||
|
When I sign in as "alice@alice.alice"
|
||||||
|
Then I should have 2 unread private messages
|
||||||
|
And I should have 2 email delivery
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,17 @@ Then /^I send a message with subject "([^"]*)" and text "([^"]*)" to "([^"]*)"$/
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Then /^I send a message with subject "([^"]*)" and text "([^"]*)" to "([^"]*)" using keyboard shortcuts$/ do |subject, text, person|
|
||||||
|
step %(I am on the conversations page)
|
||||||
|
within("#conversation_new", match: :first) do
|
||||||
|
step %(I fill in "contact_autocomplete" with "#{person}")
|
||||||
|
step %(I press the first ".as-result-item" within ".as-results")
|
||||||
|
step %(I fill in "conversation_subject" with "#{subject}")
|
||||||
|
step %(I fill in "conversation_text" with "#{text}")
|
||||||
|
find("#conversation_text").native.send_keys :control, :return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
When /^I reply with "([^"]*)"$/ do |text|
|
When /^I reply with "([^"]*)"$/ do |text|
|
||||||
step %(I am on the conversations page)
|
step %(I am on the conversations page)
|
||||||
step %(I press the first ".conversation" within ".conversations")
|
step %(I press the first ".conversation" within ".conversations")
|
||||||
|
|
@ -26,6 +37,13 @@ When /^I reply with "([^"]*)"$/ do |text|
|
||||||
step %(I press "Reply")
|
step %(I press "Reply")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
When /^I reply with "([^"]*)" using keyboard shortcuts$/ do |text|
|
||||||
|
step %(I am on the conversations page)
|
||||||
|
step %(I press the first ".conversation" within ".conversations")
|
||||||
|
step %(I fill in "message_text" with "#{text}")
|
||||||
|
find("#message_text").native.send_keys :control, :return
|
||||||
|
end
|
||||||
|
|
||||||
Then /^I send a mobile message with subject "([^"]*)" and text "([^"]*)" to "([^"]*)"$/ do |subject, text, person|
|
Then /^I send a mobile message with subject "([^"]*)" and text "([^"]*)" to "([^"]*)"$/ do |subject, text, person|
|
||||||
step %(I am on the conversations page)
|
step %(I am on the conversations page)
|
||||||
step %(I follow "New conversation")
|
step %(I follow "New conversation")
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ describe("app.views.CommentStream", function(){
|
||||||
form.submit(submitCallback);
|
form.submit(submitCallback);
|
||||||
|
|
||||||
var e = $.Event("keydown", { keyCode: 13 });
|
var e = $.Event("keydown", { keyCode: 13 });
|
||||||
e.shiftKey = false;
|
e.ctrlKey = false;
|
||||||
this.view.keyDownOnCommentBox(e);
|
this.view.keyDownOnCommentBox(e);
|
||||||
|
|
||||||
expect(submitCallback).not.toHaveBeenCalled();
|
expect(submitCallback).not.toHaveBeenCalled();
|
||||||
|
|
|
||||||
|
|
@ -1,54 +1,76 @@
|
||||||
describe("app.views.Conversations", function(){
|
describe("app.views.Conversations", function(){
|
||||||
describe('setupConversation', function() {
|
describe("setupConversation", function() {
|
||||||
context('for unread conversations', function() {
|
context("for unread conversations", function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
spec.loadFixture('conversations_unread');
|
spec.loadFixture("conversations_unread");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('removes the unread class from the conversation', function() {
|
it("removes the unread class from the conversation", function() {
|
||||||
expect($('.conversation-wrapper > .conversation.selected')).toHaveClass('unread');
|
expect($(".conversation-wrapper > .conversation.selected")).toHaveClass("unread");
|
||||||
new app.views.Conversations();
|
new app.views.Conversations();
|
||||||
expect($('.conversation-wrapper > .conversation.selected')).not.toHaveClass('unread');
|
expect($(".conversation-wrapper > .conversation.selected")).not.toHaveClass("unread");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('removes the unread message counter from the conversation', function() {
|
it("removes the unread message counter from the conversation", function() {
|
||||||
expect($('.conversation-wrapper > .conversation.selected .unread_message_count').length).toEqual(1);
|
expect($(".conversation-wrapper > .conversation.selected .unread_message_count").length).toEqual(1);
|
||||||
new app.views.Conversations();
|
new app.views.Conversations();
|
||||||
expect($('.conversation-wrapper > .conversation.selected .unread_message_count').length).toEqual(0);
|
expect($(".conversation-wrapper > .conversation.selected .unread_message_count").length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('decreases the unread message count in the header', function() {
|
it("decreases the unread message count in the header", function() {
|
||||||
var badge = '<div id="conversations_badge"><div class="badge_count">3</div></div>';
|
var badge = "<div id=\"conversations_badge\"><div class=\"badge_count\">3</div></div>";
|
||||||
$('header').append(badge);
|
$("header").append(badge);
|
||||||
expect($('#conversations_badge .badge_count').text().trim()).toEqual('3');
|
expect($("#conversations_badge .badge_count").text().trim()).toEqual("3");
|
||||||
expect($('.conversation-wrapper > .conversation.selected .unread_message_count').text().trim()).toEqual('2');
|
expect($(".conversation-wrapper > .conversation.selected .unread_message_count").text().trim()).toEqual("2");
|
||||||
new app.views.Conversations();
|
new app.views.Conversations();
|
||||||
expect($('#conversations_badge .badge_count').text().trim()).toEqual('1');
|
expect($("#conversations_badge .badge_count").text().trim()).toEqual("1");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('removes the badge_count in the header if there are no unread messages left', function() {
|
it("removes the badge_count in the header if there are no unread messages left", function() {
|
||||||
var badge = '<div id="conversations_badge"><div class="badge_count">2</div></div>';
|
var badge = "<div id=\"conversations_badge\"><div class=\"badge_count\">2</div></div>";
|
||||||
$('header').append(badge);
|
$("header").append(badge);
|
||||||
expect($('#conversations_badge .badge_count').text().trim()).toEqual('2');
|
expect($("#conversations_badge .badge_count").text().trim()).toEqual("2");
|
||||||
expect($('.conversation-wrapper > .conversation.selected .unread_message_count').text().trim()).toEqual('2');
|
expect($(".conversation-wrapper > .conversation.selected .unread_message_count").text().trim()).toEqual("2");
|
||||||
new app.views.Conversations();
|
new app.views.Conversations();
|
||||||
expect($('#conversations_badge .badge_count').text().trim()).toEqual('0');
|
expect($("#conversations_badge .badge_count").text().trim()).toEqual("0");
|
||||||
expect($('#conversations_badge .badge_count')).toHaveClass('hidden');
|
expect($("#conversations_badge .badge_count")).toHaveClass("hidden");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
context('for read conversations', function() {
|
context("for read conversations", function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
spec.loadFixture('conversations_read');
|
spec.loadFixture("conversations_read");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not change the badge_count in the header', function() {
|
it("does not change the badge_count in the header", function() {
|
||||||
var badge = '<div id="conversations_badge"><div class="badge_count">3</div></div>';
|
var badge = "<div id=\"conversations_badge\"><div class=\"badge_count\">3</div></div>";
|
||||||
$('header').append(badge);
|
$("header").append(badge);
|
||||||
expect($('#conversations_badge .badge_count').text().trim()).toEqual('3');
|
expect($("#conversations_badge .badge_count").text().trim()).toEqual("3");
|
||||||
new app.views.Conversations();
|
new app.views.Conversations();
|
||||||
expect($('#conversations_badge .badge_count').text().trim()).toEqual('3');
|
expect($("#conversations_badge .badge_count").text().trim()).toEqual("3");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("keyDown", function(){
|
||||||
|
beforeEach(function() {
|
||||||
|
this.submitCallback = jasmine.createSpy().and.returnValue(false);
|
||||||
|
spec.loadFixture("conversations_read");
|
||||||
|
new app.views.Conversations();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should submit the form with ctrl+enter", function(){
|
||||||
|
$("form#new_message").submit(this.submitCallback);
|
||||||
|
var e = $.Event("keydown", { keyCode: 13, ctrlKey: true });
|
||||||
|
$("textarea#message_text").trigger(e);
|
||||||
|
expect(this.submitCallback).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shouldn't submit the form without the ctrl key", function(){
|
||||||
|
$("form#new_message").submit(this.submitCallback);
|
||||||
|
var e = $.Event("keydown", { keyCode: 13, ctrlKey: false });
|
||||||
|
$("textarea#message_text").trigger(e);
|
||||||
|
expect(this.submitCallback).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue