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

Fixing keyboard shortcuts #27374

Closed
wants to merge 15 commits into from
Closed

Fixing keyboard shortcuts #27374

wants to merge 15 commits into from

Conversation

noveens
Copy link
Contributor

@noveens noveens commented Mar 13, 2017

Description

I am trying to fix and introduce newer keyboard shortcuts.

Changes can be tested at : http://noveen.tk/core
Username : owncloud
password : 123

IMO we should try to implement a new page in settings named controls, so that the user can customise their shortcuts. (comments?)

Till now I have managed to fix various shortcuts plus introduce new shortcuts (I will keep adding them here, feel free to add shortcuts and I'll be happy to implement them)
These implementations include proper error messages plus testers for this branch are welcome !

  • shift+d: new directory
  • shift+n: new file
  • shift+r: rename file/folder
  • shift+f: favorite file/folder (multiple allowed)
  • esc (while new file context menu is open): close menu
  • esc (while upload happening): cancel the upload
  • esc (while multiple files selected): de-select all files
  • up/down: select file/folder
  • enter: open file/folder
  • delete: delete file/folder (multiple files also allowed)
  • backspace: go back to parent folder
  • shift+up/down: select multiple files

Related Issue

#27359 #9740 #19442 #27580

Motivation and Context

Enhancement.

How Has This Been Tested?

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@PVince81 , Please guide me on this one 😄

@mention-bot
Copy link

@noveens, thanks for your PR! By analyzing the history of the files in this pull request, we identified @eriksargent, @Kondou-ger and @DeepDiver1975 to be potential reviewers.


function favorite() {
var countSelected = 0;
$("#fileList tr").each(function(index) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will not work. Try having more than 50 files in the list.
Then use the "select all" checkbox without scrolling down.
Then favorite.

It will miss the other entries. Need special handling.

This is because it doesn't render the next items as "tr" until you scroll down, for performance (pagination).

Might affect other shortcuts as well so I recommend to test this scenario with the other actions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On another note, the selector #fileList tr.select would be way more direct

Copy link
Contributor Author

@noveens noveens Mar 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PVince81 ,
I'm having issues trying to get focus on the selected table row while I press the DOWN arrow key beyond the screen.

can you please give me some pointers so as to scroll the screen when the "mouseOver" tr gets lower than the screen?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, that can be quite a struggle.

You need to get the scroll container of the list and then set its 'scrollTop' value to make it scroll down. I don't remember the details.

You can find the scroll container element by inspecting the this.$container value of the FileList instance.

The most difficult part here with shortcuts is that you're trying to operate directly on the DOM instead of talking with the matching FileList instance. Currently it's not possible to get the current FileList from the files App object. Maybe this could be extended to make such API calls easier.

@noveens
Copy link
Contributor Author

noveens commented Mar 13, 2017

Also @PVince81 ,

I was thinking of implementing a controls page under personal settings,
Which would display the current list of controls and those would be editable, values of which will be stored in a database.
Does this seem good, should I start work on this?

@PVince81
Copy link
Contributor

I was thinking of implementing a controls page under personal settings,
Which would display the current list of controls and those would be editable, values of which will be stored in a database.

I think this is not needed as it is too much of a corner case. Keep it simple, sensible defaults.

@noveens
Copy link
Contributor Author

noveens commented Mar 14, 2017

@PVince81 ,
We should at least list the shortcuts somewhere.

They're no use unless listed somewhere.

@PVince81
Copy link
Contributor

List them in the documentation then. Then need to find a place to put the link in the UI to access it.

@noveens
Copy link
Contributor Author

noveens commented Mar 14, 2017

How about "general" settings under the personal tab?

@noveens
Copy link
Contributor Author

noveens commented Mar 20, 2017

@PVince81 ,
First up, sorry for so much delay, had exams in my university 😉

Until now,
I have managed to :

  • show the selected file at centre of screen
  • if select all checkbox is true, all files are made favourite not only the view ones.
  • apply above check while deleting files.
  • write the documentation 😢
  • give link of controls' documentation in settings

Anything else I am missing?

Additions:

  • use spacebar to toggle the sidebar

Thanks 😄

@PVince81
Copy link
Contributor

Something I'm missing now (which could be done separately) is a key to open the sidebar.
Currently the enter key opens the entry with the default action.
I'm not sure what key would be best for this, maybe spacebar ?

  • BUG: shift+d, shift-n, shift-r do not seem to work on my chromium browser, they don't do anything while arrow keys work
  • design issue: the highlight for the entry viewed in the sidebar conflicts with the arrow keys thing (to be discussed separately)
  • BUG: create a big list of files, then use the arrow up key to jump to the last item: it scrolls. Then use arrow down, it will select the first item but will not scroll. Only when hitting arrow down again will it scroll.
  • BUG: regardless which letter I push (ex: "O"), the cursor goes down as if I hit the arrow down key. Maybe there is some event mix up somewhere.

Did you solve the issue for when the list has 100 entries and only the first page is rendered ? What happens if you hit arrow up, will it render all pages first ?

@noveens
Copy link
Contributor Author

noveens commented Mar 20, 2017

@PVince81 ,
Thanks for the review 😄

  • I can't seem to reproduce that any key moves the cursor.
  • Even I thought about pressing up key while at page 1, it makes the cursor to last element in page 1, while loading the next page. (SUGGESTION : remove cycled navigation)
  • About chromium, the shortcuts seem to work on chrome + firefox, I'll test on chromium.

EDIT:
The shortcuts work on chromium as well.

@noveens
Copy link
Contributor Author

noveens commented Mar 20, 2017

@PVince81 , views?

@PVince81
Copy link
Contributor

PVince81 commented Mar 22, 2017

Seems that after clearing the cache it works correctly on my Chromium 56. It did really weird shit.

I also tested what happens if I hit shortcuts while in the rename field, it seems they are not triggered which is good.

  • Please don't use backspace for deletion. I'd rather have backspace go to the parent folder as it's less dangerous.

@noveens
Copy link
Contributor Author

noveens commented Mar 22, 2017

@PVince81 ,
I am currently simulating a back button when pressing backspace.
Should I update it to specifically go to the parent folder (if not at root dir)?

@PVince81
Copy link
Contributor

I think let it go to the parent folder, not the previously visited folder.

Interestingly when I hit Backspace Chromium tells me "please use alt+left" to go to previous page. I think backspace used to be the "browser back" button shortcut. Not sure about other browsers though.

@noveens
Copy link
Contributor Author

noveens commented Mar 22, 2017

@PVince81 ,
I now call the API to change the directory to go to the parent directory rather than simulating a back button 😄
Can you have a look?

Thanks.

@noveens
Copy link
Contributor Author

noveens commented Mar 22, 2017

@tomneedham ,
can you please review? 😄

Thanks.

@PVince81
Copy link
Contributor

PVince81 commented Mar 23, 2017

  • BUG: up arrow wrap with multiple pages doesn't jump to correct entry
  1. Create 100 folders: for I in $(seq 1 100); do curl -X MKCOL -u admin:admin "http://localhost/owncloud/remote.php/webdav/$I"; done
  2. Load the page (in Chromium)
  3. Hit the "up" arrow

Expected: goes to the last item 100
Actual: goes to the last item of the current page which is 20

  • BUG: esc key doesn't close "new folder" menu on Chromium

Given that this PR is already an improvement I'd be fine merging this first and fixing the issues separately.

@PVince81
Copy link
Contributor

PVince81 commented Mar 23, 2017

Ah, forgot to test the public link page:

Public link page

  • BUG: arrow keys do not seem to scroll down the container and also prevents next page to be loaded, so even though I have 100 files in the folder it wraps already around 20 (the visible entries)

  • BUG: public link page shows many errors about


update_view @ keyboardshortcuts.js?v=323841b…:133
select_down @ keyboardshortcuts.js?v=323841b…:197
(anonymous) @ keyboardshortcuts.js?v=323841b…:486
dispatch @ jquery.min.js:3
r.handle @ jquery.min.js:3
keyboardshortcuts.js?v=323841b…:133 Uncaught TypeError: Cannot read property 'fileList' of undefined
    at update_view (keyboardshortcuts.js?v=323841b…:133)
    at select_down (keyboardshortcuts.js?v=323841b…:197)
    at HTMLDocument.<anonymous> (keyboardshortcuts.js?v=323841b…:486)
    at HTMLDocument.dispatch (jquery.min.js:3)
    at HTMLDocument.r.handle (jquery.min.js:3)
  • BUG: when link share is read-only, hitting "Shift-D" still displays the folder creation popup

you might need another approach to access to fileList instance.

Other sections

For example "Favorites" section.

  • BUG: the arrow keys do not work there at all, probably because the keyboard module is targetting only the default list.

AFAIK there is no easy way to talk to the currently visible FileList instance.
But maybe if the keyboard stuff is rewritten as a FileList plugin then it could work.

My main worry about the current file shortcut code is that it isn't really well integrated (it's very old code from back when there was only one file list view).

$scrollContainer = $('body');
}

if ($(".mouseOver").position().top >= this.$container.height() / 2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please never use absolute selectors, they are inefficient because they'd need to scan the whole page to find elements.

Use specific selectors, for example this.$el.find('.mouseOver')

/**
* Favorite all files in the current fileList
*/
favoriteAll: function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, this belongs in the favorite plugin file, not the main list

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure.

/**
* Delete all files in the current fileList
*/
deleteAll: function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer not having a keyboard shortcut that deletes ALL files. The user must first select everything manually (ctrl+a?) and then hit delete. No direct shortcut.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is called only when the user clicks the select all button via mouse and presses DEL.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there isn't any shortcut to delete all files.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Then you can try simulating a click on .delete-selected instead.

var model = this.getModelForFile(this.files[i].name);
if(!model) {
// item not loaded due to pagination
this._nextPage(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only renders the next page. What if the file is two pages down ?

In general I think the file models are already available and are not dependent on pagination, so you could simply remove this "if" block.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PVince81 ,
No, the models aren't available if the element is not being displayed on the screen.
I had to introduce the check to make sure the model is made available by showing the next page.

Also, If the element is 2 pages down, it doesn't matter, the this._nextPage(false) will be called twice (since the model for 2 page down element wouldn't also be available)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, indeed. The models won't be fully available until this big construction site is finished: #25909

will be called twice

Where does it loop ? Reading the code from top to bottom, if the second getModelForFile still returns null then you'll pass null as model to the deletion trigger.

Anyway, based on my other comment this block needs to be removed anyway as it's part of the redundant deletion code.

Copy link
Contributor Author

@noveens noveens Mar 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, the getModelForFile will never return NULL after loading the next page.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's a side effect of the way you programmed this.

Since you're iterating over all files, then it is likely that before reaching the end of the page, the previous iteration it already loaded the next page, so all subsequent calls will still succeed.

My point is that the way nextPage is implemented is that it only fetches a single next page. The way you used it seems to work somehow due to your for loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I fetch the nextPage if model isn't available loading the models of all the next page elements.

$("#new").addClass("active");
$(".popup.popupTop").toggle(true);
$('#new li[data-type="file"]').trigger('click');
$(".new").click();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally this needs to be scoped to the currently visible file list.

You could try using the selector $('#app-content .viewcontainer:not(.hidden)' as a prefix to only target the currently visible file list DOM elements.

function favorite() {
if ($("#select_all_files").is(":checked")) {
// selected all files
OCA.Files.App.fileList.favoriteAll();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OCA.Files.App.fileList is always the fileList of "All files", not the other ones.

Maybe we should store the fileList object as a data attribute of the "viewcontainer".
Basically in the FileList constructor you add this:

this.$el.data('fileList', this);

then from outside you get the currently visible view container:
var fileList = $(#app-content .viewcontainer:not(.hidden)).data('fileList').
(note: might need tweaking for public link share page)

Then in all keyboard actions you can be sure that the targetted fileList object is the current one.

@PVince81
Copy link
Contributor

@noveens there were a few comments not adressed yet. Do you intend to continue working on this ?

@codecov
Copy link

codecov bot commented Nov 24, 2017

Codecov Report

Merging #27374 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff            @@
##             master   #27374   +/-   ##
=========================================
  Coverage     62.15%   62.15%           
  Complexity    17516    17516           
=========================================
  Files          1045     1045           
  Lines         57740    57740           
=========================================
  Hits          35890    35890           
  Misses        21850    21850

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d750519...c2b9d3b. Read the comment docs.

@PVince81
Copy link
Contributor

PVince81 commented Feb 7, 2019

@noveens any interest in bringing this to completion ?

also this here would require some UX review to make sure the shortcuts are intuitive and make sense

note that our focus is now on the files app in the Phoenix project instead so not sure if we should spend more effort here (effort being dev, review, qa, etc)

@DeepDiver1975
Copy link
Member

I vote for close

@PVince81 PVince81 closed this Feb 8, 2019
@PVince81 PVince81 deleted the fixing_keyboard_shortcuts branch February 8, 2019 09:45
@lock lock bot locked as resolved and limited conversation to collaborators Feb 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants