Not possible to navigate sidebar / message list column via hotkeys alone

Tab as well as Shift+Tab should cycle through the GUI controls. More precisely, it should allow you to easily reach the left sidebar which can apparently only be accessed by using the mouse??? This is absolutely horrible, and just adding a few hotkeys to quickly switch to a few folders is no excuse. Blaming electron for such difficulties won’t help either…

Furthermore, you can not open a draft from the drafts-folder via a hotkey, neither is it possible to jump into an already written one from the inbox. The only thing you can do is to define a hotkey for the initial reply, but you cannot access the editor window of that reply later on if you ever leave it.

But it gets better: Even if you’re inside the editor window, you can’t get out of it. There’s a hotkey setting called something like “pop-sheet” in the config-file, which is apparently responsible for that, however it doesn’t do anything for me. Neither does the “Open Mail” hotkey when trying to jump into the editor.

Another issue I noticed is that you can’t press Alt+ to quickly access the drop-down menus below the title bar, which is pretty much a standard functionality in all apps. I don’t consider this feature to be essential to the general workflow of Mailspring, but it’s still something one would expect.

Update

I’ll look into automating the missing behaviour with AutoKey and offer my script here in case it should work. It can probably be ported to Autohotkey on Windows fairly easily, if someone wants to do it.


(Originally posted by a now deleted user on GitHub.)

Hey! Thanks for reporting this—this isn’t a development priority for the near future but I think we’d definitely accept a pull request improving keyboard navigation of the UI!

I use the app mostly via the keyboard personally, but I use the search hotkey a lot, up/down arrows to move through mail and the space bar to read the thread + “L” to label and triage messages. There’s been a fair bit of community interest in building a “jump bar” that lets you quickly jump to a label or folder, and that’d probably be a nicer experience than implementing keyboard navigation of the sidebar.

If you’re interested in contributing, I think a good start to this would be going through and ensuring that there’s a tabIndex on all of the interactable controls. That, combined with some CSS that ensures the tab-focused element is outlined, would allow you to navigate all the buttons via tab. I know we specifically turned that off for the composer though, because folks were super annoyed that it tabbed across every button in the toolbar instead of jumping between To/Cc/Bcc/Subject/Body as it does now.


(Originally posted by bengotow on GitHub.)

If I understand correctly, a quick-and-dirty fix (not that I would submit it) would be to just re-add the tabIndex to the sidebar controls? Or would there be something else preventing me from tabbing over its controls? If I remember correctly then I couldn’t tab anywhere except for the composer, so I guess you took the easy way and just removed all tabIndex rules except for the few elements in there?

Update 1

Actually… A fix should be fairly simple using this line of code:

document.getElementsByClassName("name")[numberIndicatingSidebarEntry].click()

I can easily traverse through the sidebar nodes that way.

Update 2

I managed to get somewhat convenient keyboard-navigation on the sidebar by injecting this code in chrome debugger:

__counterForSidebarFolders = 0;
__nameList = document.getElementsByClassName('name')

document.addEventListener("keydown", event => {
    moveDown = false;
    moveUp = false;

    if (event.ctrlKey && event.shiftKey && event.keyCode == 9) moveUp = true;
    else if (event.ctrlKey && event.keyCode == 9) moveDown = true;

    console.log(moveDown);
    console.log(moveUp);

    //Only change counter if an actual move-event happens
    if (moveDown || moveUp) {

        //The below code is necessary to always start navigation at the already selected folder
        [...document.getElementsByClassName('name')].forEach((item, index) => {
                selectedItem = document.getElementsByClassName("selected item");
                selectedItemIndex = moveDown ? selectedItem.length - 1 : 0;
                
                if (item == selectedItem[selectedItemIndex].getElementsByClassName("name")[0])
                    __counterForSidebarFolders = index;
            }
        )
    }

    //The actual keyboard-navigation...
    if(moveUp && __counterForSidebarFolders > -1) {
        __counterForSidebarFolders--
        __nameList[__counterForSidebarFolders].click()
    }
    else if(moveDown && __counterForSidebarFolders < __nameList.length)
    {
        __counterForSidebarFolders++
        __nameList[__counterForSidebarFolders].click()
    }
})

Just in case someone else needs a quickfix… It works by pressing ctrl+tab and ctrl+shift+tab but is easy to adapt to custom hotkeys. I’m currently looking into how to permanently modify the electron package (as I really doubt the code above fullfills the quality standards of Mailspring, so I’ll not attempt a pull request :wink:

Update 3

Took me some time, but I figured out the solution was to edit chrome-extension.js inside the electron.asar file. I added this code at the bottom:

app.on('browser-window-created', function (event, bWindow) {
  bWindow.webContents.executeJavaScript(`
  __counterForSidebarFolders = 0;
  __nameList = document.getElementsByClassName('name');
  
  document.addEventListener("keydown", event => {
      moveDown = false;
      moveUp = false;
  
      if (event.ctrlKey && event.shiftKey && event.keyCode == 9) moveUp = true;
      else if (event.ctrlKey && event.keyCode == 9) moveDown = true;
  
      console.log(moveDown);
      console.log(moveUp);
  
      //Only change counter if an actual move-event happens
      if (moveDown || moveUp) {
  
          //The below code is necessary to always start navigation at the already selected folder
          [...document.getElementsByClassName('name')].forEach((item, index) => {
                  selectedItem = document.getElementsByClassName("selected item");
                  selectedItemIndex = moveDown ? selectedItem.length - 1 : 0;
                  
                  if (item == selectedItem[selectedItemIndex].getElementsByClassName("name")[0])
                      __counterForSidebarFolders = index;
              }
          )
      }
  
      //The actual keyboard-navigation...
      if(moveUp && __counterForSidebarFolders > -1) {
          __counterForSidebarFolders--;
          __nameList[__counterForSidebarFolders].click();
      }
      else if(moveDown && __counterForSidebarFolders < __nameList.length)
      {
          __counterForSidebarFolders++;
          __nameList[__counterForSidebarFolders].click();
      }
  })  
  `)
})

For convencience I’ll add the re-packaged electron.asar (of the current version, will likely be outdated soon though), just replace it with mine. The location depends on your OS, on linux a simple whereis mailspring did the job. On Windows I don’t know, but you can check in your Program Files and Application Data folders or follow this guide:

sidebar-keyboard-navigation.zip

Update 4

I just noticed a bug. In case you have more than two mail accounts connected to mailspring, and you attempt to skip through their corresponding subfolders in the “All Accounts” view (ctrl+1), my code would always jump from the first to the last acount… You can probably avoid this by switching to the account-specific views (ctrl+2, ctrl+3, …), at least that issue didn’t occur for me in there. Subfolders worked just fine.

Actually I didn’t know about those shortcuts before, but they come in very handy… I mostly wrote the JS code from above to have a way to switch accounts via keyboard. Guess using those combined with the hotkeys for drafts, sent, inbox, … is an acceptable workaround though.

Update 5

Instead of browser-window-focus I used browser-window-created. Otherwise multiple EventListener would be registered each time the window gets focused on, leading to messed up jumps of multiple controls. Also fixed in the zip!

Now you just should be aware about the fact that you’ll have to re-add the changes made to the .asar file each time you update. If you really want to you can probably write up a bash script for that job though…

Update 6

I wrote a bash file myself. It’s intended mostly for personal usage but in case Mailspring’s electron.asar archive is in /usr/share/mailspring/resources it should work for you as well:

mailspring-update-fix.zip

Just execute it after each update and you should be fine. The chrome-extension.js file containing the actual fix is hidden, in case you wonder.


(Originally posted by a now deleted user on GitHub.)