Skip to content

Commit

Permalink
Improved scrolling and mouse/kbd interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
pjeby committed Aug 30, 2021
1 parent 7dab54a commit 0430b74
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 21 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Quick Explorer for Obsidian

[Obsidian](https://obsidian.md)'s in-app file explorer is pretty flexible, but it's almost 100% mouse-driven with almost no keyboard navigation. Worse, if you have a lot of folders and lots of files in them, you end up spending a lot of time expanding and collapsing folders, and scrolling to find what you're looking for. This can be especially annoying when all you want is to do something with the "current" folder, or a parent of it... *without* needing to open a sidebar and close it again afterwards. And last, but not least, trying to rapidly preview the contents of a lot of notes with the mouse is a giant PITA.
[Obsidian](https://obsidian.md)'s in-app file explorer is pretty flexible, but it's almost 100% mouse-driven and not at all keyboard-friendly. Worse, if you have a lot of folders with lots of files in them, you can spend a lot of time expanding and collapsing folders, and scrolling around to find what you're looking for. This can be especially annoying when all you want is to do something with the "current" folder, or a parent of it... *without* needing to open a sidebar and close it again afterwards. (And last, but not least, trying to rapidly preview the contents of a lot of notes with the mouse is a giant PITA.)

Enter Quick Explorer. It's menu-based and keyboard-friendly, stays out of your way when you aren't using it, and makes it super-easy to navigate from either the vault root or current folder, without needing to scroll through or collapse a zillion other folders to find what you're looking for. You can even search by name within a folder, just by typing. There's an auto-preview feature that makes previewing lots of notes super easy, with no mousing and no popups overhanging the file list. And you can even see the path of the current file as a "breadcrumbs bar" in the window title bar!

Expand Down
44 changes: 39 additions & 5 deletions main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "quick-explorer",
"name": "Quick Explorer",
"version": "0.0.7",
"version": "0.0.8",
"description": "Perform file explorer operations (and see your current file path) from the title bar",
"minAppVersion": "0.12.12",
"isDesktopOnly": true
Expand Down
4 changes: 2 additions & 2 deletions src/FolderMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,9 @@ export class FolderMenu extends PopupMenu {
return super.hide();
}

select(idx: number) {
select(idx: number, scroll = true) {
const old = this.selected;
super.select(idx);
super.select(idx, scroll);
if (old !== this.selected) {
// selected item changed; trigger new popover or hide the old one
if (autoPreview) this.showPopover(); else this.hidePopover();
Expand Down
46 changes: 43 additions & 3 deletions src/menus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ declare module "obsidian" {

select(n: number): void
selected: number
onArrowDown?(e: KeyboardEvent): false
onArrowDown(e: KeyboardEvent): false
onArrowUp(e: KeyboardEvent): false
}

Expand Down Expand Up @@ -55,19 +55,34 @@ export class PopupMenu extends Menu {
const ret = prev.call(this, target) || menu.child?.dom.contains(target);
return ret;
}}});
this.dom.addClass("qe-popup-menu");
}

onload() {
this.scope.register(null, null, this.onKeyDown.bind(this));
super.onload();
this.visible = true;
// We wait until now to register so that any initial mouseover of the old mouse position will be skipped
this.register(onElement(this.dom, "mouseover", ".menu-item", (event: MouseEvent, target: HTMLDivElement) => {
if (mouseMoved(event) && !target.hasClass("is-disabled")) {
this.select(this.items.findIndex(i => i.dom === target), false);
}
}));
}

onunload() {
this.visible = false;
super.onunload();
}

// Override to avoid having a mouseover event handler
addItem(cb: (i: MenuItem) => any) {
const i = new MenuItem(this);
this.items.push(i);
cb(i);
return this;
}

onKeyDown(event: KeyboardEvent) {
const mod = Keymap.getModifiers(event);
if (event.key.length === 1 && !event.isComposing && (!mod || mod === "Shift") ) {
Expand Down Expand Up @@ -111,10 +126,14 @@ export class PopupMenu extends Menu {
return false;
}

select(n: number) {
select(n: number, scroll = true) {
this.match = "" // reset search on move
super.select(n);
this.items[this.selected].dom.scrollIntoView()
if (scroll) {
const el = this.items[this.selected].dom;
const me = this.dom.getBoundingClientRect(), my = el.getBoundingClientRect();
if (my.top < me.top || my.bottom > me.bottom) el.scrollIntoView();
}
}

unselect() {
Expand Down Expand Up @@ -190,6 +209,7 @@ export class PopupMenu extends Menu {
}

// Done! Show our work.
if (event instanceof MouseEvent) mouseMoved(event);
this.showAtPosition(point);

// Flag the clicked item as active, until we close
Expand All @@ -204,4 +224,24 @@ export class PopupMenu extends Menu {

function escapeRegex(s: string) {
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

let oldX = 0, oldY = 0

function mouseMoved({clientX, clientY}: {clientX: number, clientY: number}) {
if ( Math.abs(oldX-clientX) || Math.abs(oldY-clientY) ) {
oldX = clientX;
oldY = clientY;
return true;
}
return false;
}

function onElement<K extends keyof HTMLElementEventMap>(
el: HTMLElement, type: K, selector:string,
listener: (this: HTMLElement, ev: HTMLElementEventMap[K], delegateTarget: HTMLElement) => any,
options: boolean | AddEventListenerOptions = false
) {
el.on(type, selector, listener, options)
return () => el.off(type, selector, listener, options);
}
7 changes: 5 additions & 2 deletions src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@
}
}

.menu-item {
.qe-popup-menu .menu-item {
display: flex;
&.selected:not(:hover) {
&.selected {
background-color: var(--background-secondary-alt);
}
&:hover:not(.selected) {
background-color: var(--background-primary);
}

// Expand the title so the extension tag will be right-aligned
.menu-item-title { flex-grow: 1; }
Expand Down
14 changes: 8 additions & 6 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@
color: var(--text-on-accent);
opacity: 1; }

.menu-item {
.qe-popup-menu .menu-item {
display: flex; }
.menu-item.selected:not(:hover) {
.qe-popup-menu .menu-item.selected {
background-color: var(--background-secondary-alt); }
.menu-item .menu-item-title {
.qe-popup-menu .menu-item:hover:not(.selected) {
background-color: var(--background-primary); }
.qe-popup-menu .menu-item .menu-item-title {
flex-grow: 1; }
.menu-item .nav-file-tag {
.qe-popup-menu .menu-item .nav-file-tag {
margin-top: 5px;
margin-left: 1.5em;
opacity: 0.4;
background-color: transparent; }
.menu-item:hover, .menu-item.selected {
.qe-popup-menu .menu-item:hover, .qe-popup-menu .menu-item.selected {
color: var(--text-normal); }
.menu-item:hover .nav-file-tag, .menu-item.selected .nav-file-tag {
.qe-popup-menu .menu-item:hover .nav-file-tag, .qe-popup-menu .menu-item.selected .nav-file-tag {
opacity: 1; }
2 changes: 1 addition & 1 deletion versions.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"0.0.7": "0.12.12",
"0.0.8": "0.12.12",
"0.0.5": "0.12.10",
"0.0.1": "0.12.3"
}

0 comments on commit 0430b74

Please sign in to comment.