Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from Feb 7, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Expand Up @@ -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

Expand Down
46 changes: 37 additions & 9 deletions app/assets/javascripts/app/views/stream/shortcuts.js
Expand Up @@ -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) {
Expand All @@ -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":
Expand All @@ -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"];
Expand All @@ -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:
}
},
Expand All @@ -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]);
Expand All @@ -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]);
Expand All @@ -86,23 +98,39 @@ 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');
selected.removeClass('shortcut_selected').removeClass('highlighted');
//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
Expand Down
3 changes: 3 additions & 0 deletions app/assets/templates/faq_keyboard_shortcuts_tpl.jst.hbs
Expand Up @@ -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>
15 changes: 9 additions & 6 deletions config/locales/diaspora/en.yml
Expand Up @@ -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?"
Expand Down Expand Up @@ -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!
Expand Down
114 changes: 92 additions & 22 deletions spec/javascripts/app/views/stream/shortcuts_spec.js
@@ -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();
Expand All @@ -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');
Expand All @@ -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(){
Expand All @@ -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');
Expand All @@ -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(){
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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();
});
});
});