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

[FR] Don't close tabs, but switch focus #18

Closed
FynnFreyer opened this issue Jan 17, 2024 · 19 comments
Closed

[FR] Don't close tabs, but switch focus #18

FynnFreyer opened this issue Jan 17, 2024 · 19 comments
Labels
enhancement New feature or request feature request linear Created by Linear-GitHub Sync
Milestone

Comments

@FynnFreyer
Copy link

When I have a note opened already in a background tab, and then try to open this note via the quick switcher it closes the foreground note. I would feel like just switching tabs would be preferrable.

Tab closing instead of switching

This is a matter of opinion obviously, and the default behaviour would also discard the active note, but this would for example enable quick and easy navigation between open tabs via the quick switcher.

@czottmann
Copy link
Owner

Hi @FynnFreyer, thanks for the ticket!

This is a matter of opinion obviously, and the default behaviour would also discard the active note, but this would for example enable quick and easy navigation between open tabs via the quick switcher.

I concur, and I'd love to implement it but AFAICT there's no event Mononote could hook into to learn about the quick switcher use. Meaning, to the best of my knowledge Obsidian doesn't signal that the quick switcher does anything, Mononote can only react to the change in the active tab but doesn't see how it came to be.

I'll keep the ticket open, as it's a valid feature request (plus I'd love to make it happen), maybe someone more knowledgeable than me might chime in, or maybe I'll have an epiphany at some point.

@FynnFreyer
Copy link
Author

Hey @czottmann, no worries, thanks for making this plugin =D

[...] there's no event Mononote could hook into [...], Mononote can only react to the change in the active tab

Yes, that's tricky =/

Just generating ideas here, but caveat emptor: they might be bad =)
(I don't know my way around the Obsidian-API or TypeScript)

I think it's possible, to use Workspace.getLastOpenFiles to find out which file lost focus. Then one would need to check whether this one was open in the current pane and if it was, but it's not anymore, restore it and only afterwards switch to the duplicate note.

If we open a new tab, and the old one is still there, we can check that it's still there. If it isn't, we could restore it. The problem is, that if it isn't there, we might have just come from another window, or a popover.

To alleviate that, one could probably do the bookkeeping internally (shudder) and keep a reference to the last focused file, which is updated on changes, using Workspace.getActiveViewOfType or some such. Then, when the focus changes, you know which view lost focus, and can even recognize if that's due to a popover or another window (assuming that a View/Leaf can find out where it is). (Could this even allow for #16 without breaking hover editor?)

Seems like a lot, but might be worth it. I'll sleep it over, and if you're interested, and I find the time (soon™) I'd put some effort in detailing and maybe even implementing this.

@5HT2
Copy link

5HT2 commented Jan 23, 2024

I'd really love this as an option / default, I found this through the https://github.com/scambier/obsidian-no-dupe-leaves plugin (which only seems to affect clicking a link, not the Quick Switcher feature in Obsidian), I almost exclusively use quick switchers to navigate opened windows / apps OS-wide, as well as different files and terminal tabs elsewhere, as it reduces mouse strain from nerve damage in my hands, and currently in order to avoid opening a duplicate note with the quick switcher I need to

  1. Look at my opened tabs to see if I already have it opened
    2a. Ctrl T if I don't → Use Quick Switcher
    3b. If I do, use arrow keys / other navigation shortcuts to switch to that note

This plugin is wonderful in that it avoids the duplication behavior with the quick switcher, but unfortunately replacing the current window is somewhat disruptive (even if avoidable by doing Ctrl T → Quick Switcher → use mononote), I think this feature would be very helpful :)

@czottmann
Copy link
Owner

Thanks, people, I appreciate the input! I will see what I can do but it might take a bit, as Mononote is not my priority right now.

@czottmann czottmann added this to the Mononote 1.2 milestone Jan 24, 2024
@FynnFreyer
Copy link
Author

I will see what I can do but [...] Mononote is not my priority right now

As I said, I'd be willing to detail and implement this and send a PR. It might take a while, but will happen eventually, because I want this for myself

@czottmann
Copy link
Owner

@FynnFreyer Feel free to give it a shot! I believe it can be solved by checking the history of the newly activated tab, and if there is history, instead of closing it before focussing the already existing note, we could go back one step. Just from the top of my head…

@czottmann czottmann added linear Created by Linear-GitHub Sync enhancement New feature or request labels Feb 1, 2024
@Tejeev
Copy link

Tejeev commented Apr 4, 2024

Thank you @czottmann! This addon is a great help and I think if we can get something like what you described in the last comment, that would be a great solution. Here's hoping Obsidian has a way for that when someone gets the time to try it.
Not pushing for a more speedy release but wanted to +1 the RFE and also show my appreciation :)

@Tejeev
Copy link

Tejeev commented May 3, 2024

@lifehaschanged re-opening the last closed tab after switching still loses prior history iiuc. I prefer the workaround @czottmann proposed, though I can see why it's maybe not the best, as you might end up with tabs on pages you didn't remember why you had open. Any solution that loses history is pointless to me. Another alternative might be that when it notices a new tab opening to a page that is already open, the addon closes the new tab and goes to the existing one, rather than the other way around, or just goes to the existing tab rather than even opening a new one (I think the former is more possible here?)

@czottmann
Copy link
Owner

czottmann commented May 8, 2024

Thanks for all the input, folks, really appreciate it. Sorry about the absence, but this here is a side project, and I need to make money to pay rent, so those projects get higher priority. 🤷🏻‍♂️


I took some time to dive deeper into how Obsidian handles things, and I'm at a loss at how to proceed. Before I proceed with the distilled version of what I found out, let's recap: Mononote can only react to events triggered by Obsidian, namely the active-leaf-changed event. There's no "before" hook here, i.e. the event is always triggered after the fact. AFAICT there's no other event besides (maybe?) file-open that emits a signal that the currently focussed tab was changed.

Now going back to the original example, simplified: We have two tabs, T1 w/ note N1, and T2 w/ note N2. N1 contains a link to N2. Clicking that link should focus T2 (N2), but T1 shouldn't close but go back in history, effectively show N1 again.

Tricky. I've experimented with checking the history of the currently open tab (T1), and if there is back history, keeping the tab open instead of closing it, and going back. Calling workspaceLeaf.history.back() etc., however, does two things:

  • It'll trigger the history-change event 👍🏼
  • It'll bring the leaf/tab in question to the fore 🫤

The latter has the effect that the just-focussed tab doesn't remain in focus, plus now there's yet another active-leaf-changed event, starting a new cycle with a race condition on top.

To be honest, again, I'm at a loss about where to go from here. I'm open to suggestions.

Copy link

linear bot commented May 8, 2024

@lifehaschanged
Copy link

Why can't everything stay as it is, and when a link is clicked, only a new empty tab is opened before switching to the other targeted tab? This way, only the empty tab would be closed, leaving the other one intact. I can already test this in Obsidian with the current Mononote setting: when I switch from an empty tab to another tab, only the empty tab is closed. It would just require inserting Obsidian's internal command for a new tab before the actual tab switch.

@jamie9090
Copy link

I would love this as well. Hopefully Obsidian implements directly! Obsidian workspaces can become so messy.

@czottmann
Copy link
Owner

@lifehaschanged

Why can't everything stay as it is, and when a link is clicked, only a new empty tab is opened before switching to the other targeted tab? This way, only the empty tab would be closed, leaving the other one intact. I can already test this in Obsidian with the current Mononote setting: when I switch from an empty tab to another tab, only the empty tab is closed. It would just require inserting Obsidian's internal command for a new tab before the actual tab switch.

In order to open a new tab, Mononote would need to know when to open that new tab. It's a reactive plugin, and only listens to notifications that Obsidian is sending out. And there's no notification for "Obsidian is about to open a link" that we could hook into. The app does its thing, and then, when it's done doing that, sends out a notification "I've focussed a tab", including the pointer to the tab. There's also a "I've opened a file" notification (which includes a pointer to the opened file, but none to the tab that holds the file).

And Mononote mustn't cram anything into Obsidian's own source code, there be dragons, not to mention it'd be rude AF ;)

@czottmann czottmann pinned this issue Jun 18, 2024
@czottmann
Copy link
Owner

czottmann commented Jun 19, 2024

A short update: I'm currently rewriting the whole internal logic.

I've ditched the idea of closing any superfluous tabs, which makes the whole process a lot less brittle. Instead, when a tab (T1) gets activated/focussed, all its siblings are tested for T1's displayed note. If any tabs are found, the oldest (T2) is activated/focussed while T1 will return to its previous note. If there is no previous note, T1 is closed.

The app's event loops are chock-full of possible race conditions and surprises. For example, when a tab's active-leaf-change event is sent out, the tab's history isn't updated yet. 😐 (Something I hadn't realized before.) And going back in a tab's history will trigger another active-leaf-change event which Mononote has to ignore. So… complexity.

Anyway, it's working quite well right now but as we all know, the devil's in the edge cases. 😉 I'll run some more tests later, fingers crossed!

@czottmann
Copy link
Owner

Fixed/implemented in Release 1.2.1. Let me know if it isn't, please!

@kvenn
Copy link

kvenn commented Jun 20, 2024

Works like a dream. You rock @czottmann 🙏

@jamie9090
Copy link

jamie9090 commented Jun 21, 2024 via email

@CarlossShi
Copy link

In order to open a new tab, Mononote would need to know when to open that new tab. It's a reactive plugin, and only listens to notifications that Obsidian is sending out. And there's no notification for "Obsidian is about to open a link" that we could hook into. The app does its thing, and then, when it's done doing that, sends out a notification "I've focussed a tab", including the pointer to the tab. There's also a "I've opened a file" notification (which includes a pointer to the opened file, but none to the tab that holds the file).

And Mononote mustn't cram anything into Obsidian's own source code, there be dragons, not to mention it'd be rude AF ;)
@czottmann, #18 (comment)

I'm trying to understand the logic of this plugin. Do you mean that we cannot prevent Obsidian from opening a link after we click it? IMO, the desired way is not to open a new tab if it already exists, rather than open one and then close it. Is that impossible?

@czottmann
Copy link
Owner

@CarlossShi That is correct. Mononote is reactive not least because Obsidian doesn't emit any type of "beforeFileOpen" events. It opens a new tab, then emits an "I'm done" type of event.

To prevent that, one would need to inject code into Obsidian itself (as opposed to work with the plugin API). I won't do that, as a) it's bad form, and b) there be dragons.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request feature request linear Created by Linear-GitHub Sync
Projects
None yet
Development

No branches or pull requests

8 participants