Add shortcuts for reshare, expand Post and open first link in a post

This commit is contained in:
Faldrian 2015-01-28 15:17:21 +01:00
parent aaadf2926f
commit 099974ddef
5 changed files with 142 additions and 37 deletions

View file

@ -154,6 +154,7 @@ diaspora.yml file**. The existing settings from 0.4.x and before will not work a
* Hide user setting if the community spotlight is not enabled on the pod [#5562](https://github.com/diaspora/diaspora/pull/5562)
* Add HTML view for pod statistics [#5464](https://github.com/diaspora/diaspora/pull/5464)
* Added/Moved hide, block user, report and delete button in SPV [#5547](https://github.com/diaspora/diaspora/pull/5547)
* Added keyboard shortcuts r(reshare), m(expand Post), o(open first link in post) [#5602](https://github.com/diaspora/diaspora/pull/5602)
# 0.4.1.2

View file

@ -13,6 +13,9 @@ app.views.StreamShortcuts = {
this.on('hotkey:gotoPrev', this.gotoPrev, this);
this.on('hotkey:likeSelected', this.likeSelected, this);
this.on('hotkey:commentSelected', this.commentSelected, this);
this.on('hotkey:reshareSelected', this.reshareSelected, this);
this.on('hotkey:expandSelected', this.expandSelected, this);
this.on('hotkey:openFirstLinkSelected', this.openFirstLinkSelected, this);
},
_onHotkeyDown: function(event) {
@ -21,7 +24,7 @@ app.views.StreamShortcuts = {
if(jQuery.inArray(event.target.type, textAcceptingInputTypes) > -1){
return;
}
// trigger the events based on what key was pressed
switch (String.fromCharCode( event.which ).toLowerCase()) {
case "j":
@ -33,7 +36,7 @@ app.views.StreamShortcuts = {
default:
}
},
_onHotkeyUp: function(event) {
//make sure that the user is not typing in an input field
var textAcceptingInputTypes = ["textarea", "select", "text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", "datetime-local", "search", "color"];
@ -49,6 +52,15 @@ app.views.StreamShortcuts = {
case "l":
this.trigger('hotkey:likeSelected');
break;
case "r":
this.trigger('hotkey:reshareSelected');
break;
case "m":
this.trigger('hotkey:expandSelected');
break;
case "o":
this.trigger('hotkey:openFirstLinkSelected');
break;
default:
}
},
@ -57,7 +69,7 @@ app.views.StreamShortcuts = {
// select next post: take the first post under the header
var stream_elements = this.$('div.stream_element.loaded');
var posUser = window.pageYOffset;
for (var i = 0; i < stream_elements.length; i++) {
if(stream_elements[i].offsetTop>posUser+this._headerSize){
this.selectPost(stream_elements[i]);
@ -74,7 +86,7 @@ app.views.StreamShortcuts = {
// select previous post: take the first post above the header
var stream_elements = this.$('div.stream_element.loaded');
var posUser = window.pageYOffset;
for (var i = stream_elements.length-1; i >=0; i--) {
if(stream_elements[i].offsetTop<posUser+this._headerSize){
this.selectPost(stream_elements[i]);
@ -86,15 +98,31 @@ app.views.StreamShortcuts = {
this.selectPost(stream_elements[0]);
}
},
commentSelected: function() {
$('a.focus_comment_textarea',this.$('div.stream_element.loaded.shortcut_selected')).click();
},
},
likeSelected: function() {
$('a.like:first',this.$('div.stream_element.loaded.shortcut_selected')).click();
},
reshareSelected: function() {
$('a.reshare:first',this.$('div.stream_element.loaded.shortcut_selected')).click();
},
expandSelected: function() {
$('div.expander:first',this.$('div.stream_element.loaded.shortcut_selected')).click();
},
openFirstLinkSelected: function() {
var link = $('div.collapsible a[target="_blank"]:first',this.$('div.stream_element.loaded.shortcut_selected'));
if(link.length > 0) {
// click does only work with vanilla javascript
link[0].click();
}
},
selectPost: function(element){
//remove the selection and selected-class from all posts
var selected=this.$('div.stream_element.loaded.shortcut_selected');
@ -102,7 +130,7 @@ app.views.StreamShortcuts = {
//move to new post
window.scrollTo(window.pageXOffset, element.offsetTop-this._headerSize);
//add the selection and selected-class to new post
element.className+=" shortcut_selected highlighted";
element.className+=" shortcut_selected highlighted";
},
};
// @license-end

View file

@ -10,6 +10,9 @@
<li>{{ keyboard_shortcuts_li2 }}</li>
<li>{{ keyboard_shortcuts_li3 }}</li>
<li>{{ keyboard_shortcuts_li4 }}</li>
<li>{{ keyboard_shortcuts_li5 }}</li>
<li>{{ keyboard_shortcuts_li6 }}</li>
<li>{{ keyboard_shortcuts_li7 }}</li>
</ul>
</div>
</div>

View file

@ -565,13 +565,16 @@ en:
filter_tags_q: "How can I filter/exclude some tags from my stream?"
filter_tags_a: "This is not yet available directly through diaspora*, but some %{third_party_tools} have been written that might provide this."
keyboard_shortcuts:
title: "Keyboard shortcuts"
keyboard_shortcuts_q: "What keyboard shortcuts are available?"
keyboard_shortcuts_a1: "In the stream view you can use the following keyboard shortcuts:"
keyboard_shortcuts_li1: "j - jump to the next post"
keyboard_shortcuts_li2: "k - jump to the previous post"
keyboard_shortcuts_li3: "c - comment on the current post"
keyboard_shortcuts_li4: "l - like the current post"
title: "Keyboard shortcuts"
keyboard_shortcuts_li5: "r - reshare the current post"
keyboard_shortcuts_li6: "m - expand the current post"
keyboard_shortcuts_li7: "o - open the first link in the current post"
miscellaneous:
title: "Miscellaneous"
back_to_top_q: "Is there a quick way to go back to the top of a page after I scroll down?"
@ -825,15 +828,15 @@ en:
subject: "Your diaspora* account has been flagged for removal due to inactivity"
body: |-
Hello,
It looks as though you no longer want your account at %{pod_url}, as you haven't used it for %{after_days} days. To ensure our active users get the best performance from this diaspora* pod, we'd like to remove unwanted accounts from our database.
We'd love you to stay part of diaspora*'s community, and you're welcome to keep your account live if you want to.
If you want to keep your account live, all you need to do is to sign in to your account before %{remove_after}. When you sign in, take a moment to have a look around diaspora*. It has changed a lot since you last looked in, and we think you'll like the improvements we've made. Follow some #tags to find content you love.
Sign in here: %{login_url}. If you've forgotten your sign-in details, you can ask for a reminder on that page.
Hoping to see you again,
The diaspora* email robot!

View file

@ -1,27 +1,27 @@
describe("app.views.StreamShortcuts", function () {
beforeEach(function() {
this.post1 = factory.post({author : factory.author({name : "Rebecca Black", id : 1492})})
this.post2 = factory.post({author : factory.author({name : "John Stamos", id : 1987})})
this.post1 = factory.post({author : factory.author({name : "Rebecca Black", id : 1492})});
this.post2 = factory.post({author : factory.author({name : "John Stamos", id : 1987})});
this.stream = new app.models.Stream();
this.stream.add([this.post1, this.post2]);
this.view = new app.views.Stream({model : this.stream});
this.view.render();
expect(this.view.$('div.stream_element.loaded').length).toBe(2);
});
describe("loading the stream", function(){
it("should setup the shortcuts", function(){
spyOn(this.view, 'setupShortcuts');
spyOn(this.view, 'setupShortcuts');
this.view.initialize();
expect(this.view.setupShortcuts).toHaveBeenCalled();
});
});
describe("pressing 'j'", function(){
});
describe("pressing 'j'", function(){
it("should call 'gotoNext' if not pressed in an input field", function(){
spyOn(this.view, 'gotoNext');
this.view.initialize();
@ -31,13 +31,13 @@ describe("app.views.StreamShortcuts", function () {
this.view._onHotkeyDown(e);
expect(this.view.gotoNext).toHaveBeenCalled();
});
it("'gotoNext' should call 'selectPost'", function(){
spyOn(this.view, 'selectPost');
this.view.gotoNext();
expect(this.view.selectPost).toHaveBeenCalled();
});
it("shouldn't do anything if the user types in an input field", function(){
spyOn(this.view, 'gotoNext');
spyOn(this.view, 'selectPost');
@ -50,7 +50,7 @@ describe("app.views.StreamShortcuts", function () {
expect(this.view.selectPost).not.toHaveBeenCalled();
});
});
describe("pressing 'k'", function(){
it("should call 'gotoPrev' if not pressed in an input field", function(){
@ -62,13 +62,13 @@ describe("app.views.StreamShortcuts", function () {
this.view._onHotkeyDown(e);
expect(this.view.gotoPrev).toHaveBeenCalled();
});
it("'gotoPrev' should call 'selectPost'", function(){
spyOn(this.view, 'selectPost');
this.view.gotoPrev();
expect(this.view.selectPost).toHaveBeenCalled();
});
it("shouldn't do anything if the user types in an input field", function(){
spyOn(this.view, 'gotoPrev');
spyOn(this.view, 'selectPost');
@ -81,7 +81,7 @@ describe("app.views.StreamShortcuts", function () {
expect(this.view.selectPost).not.toHaveBeenCalled();
});
});
describe("pressing 'c'", function(){
it("should click on the comment-button if not pressed in an input field", function(){
@ -93,7 +93,7 @@ describe("app.views.StreamShortcuts", function () {
this.view._onHotkeyUp(e);
expect(this.view.commentSelected).toHaveBeenCalled();
});
it("shouldn't do anything if the user types in an input field", function(){
spyOn(this.view, 'commentSelected');
this.view.initialize();
@ -104,9 +104,9 @@ describe("app.views.StreamShortcuts", function () {
expect(this.view.commentSelected).not.toHaveBeenCalled();
});
});
describe("pressing 'l'", function(){
it("should click on the like-button if not pressed in an input field", function(){
spyOn(this.view, 'likeSelected');
this.view.initialize();
@ -116,7 +116,7 @@ describe("app.views.StreamShortcuts", function () {
this.view._onHotkeyUp(e);
expect(this.view.likeSelected).toHaveBeenCalled();
});
it("shouldn't do anything if the user types in an input field", function(){
spyOn(this.view, 'likeSelected');
this.view.initialize();
@ -127,4 +127,74 @@ describe("app.views.StreamShortcuts", function () {
expect(this.view.likeSelected).not.toHaveBeenCalled();
});
});
})
describe("pressing 'r'", function(){
it("should click on the reshare-button if not pressed in an input field", function(){
spyOn(this.view, 'reshareSelected');
this.view.initialize();
var e = $.Event("keyup", { which: 82, target: {type: "div"} });
//verify that the test is correct
expect(String.fromCharCode( e.which ).toLowerCase()).toBe('r');
this.view._onHotkeyUp(e);
expect(this.view.reshareSelected).toHaveBeenCalled();
});
it("shouldn't do anything if the user types in an input field", function(){
spyOn(this.view, 'reshareSelected');
this.view.initialize();
var e = $.Event("keyup", { which: 82, target: {type: "textarea"} });
//verify that the test is correct
expect(String.fromCharCode( e.which ).toLowerCase()).toBe('r');
this.view._onHotkeyUp(e);
expect(this.view.reshareSelected).not.toHaveBeenCalled();
});
});
describe("pressing 'm'", function(){
it("should click on the more-button if not pressed in an input field", function(){
spyOn(this.view, 'expandSelected');
this.view.initialize();
var e = $.Event("keyup", { which: 77, target: {type: "div"} });
//verify that the test is correct
expect(String.fromCharCode( e.which ).toLowerCase()).toBe('m');
this.view._onHotkeyUp(e);
expect(this.view.expandSelected).toHaveBeenCalled();
});
it("shouldn't do anything if the user types in an input field", function(){
spyOn(this.view, 'expandSelected');
this.view.initialize();
var e = $.Event("keyup", { which: 77, target: {type: "textarea"} });
//verify that the test is correct
expect(String.fromCharCode( e.which ).toLowerCase()).toBe('m');
this.view._onHotkeyUp(e);
expect(this.view.expandSelected).not.toHaveBeenCalled();
});
});
describe("pressing 'o'", function(){
it("should click on the more-button if not pressed in an input field", function(){
spyOn(this.view, 'openFirstLinkSelected');
this.view.initialize();
var e = $.Event("keyup", { which: 79, target: {type: "div"} });
//verify that the test is correct
expect(String.fromCharCode( e.which ).toLowerCase()).toBe('o');
this.view._onHotkeyUp(e);
expect(this.view.openFirstLinkSelected).toHaveBeenCalled();
});
it("shouldn't do anything if the user types in an input field", function(){
spyOn(this.view, 'openFirstLinkSelected');
this.view.initialize();
var e = $.Event("keyup", { which: 79, target: {type: "textarea"} });
//verify that the test is correct
expect(String.fromCharCode( e.which ).toLowerCase()).toBe('o');
this.view._onHotkeyUp(e);
expect(this.view.openFirstLinkSelected).not.toHaveBeenCalled();
});
});
});