RealRaven2000 / FiltaQuilla

Adds many new mail filter actions to Thunderbird
http://quickfilters.quickfolders.org/filtaquilla.html
GNU General Public License v3.0
85 stars 15 forks source link

Feature Request: new action - open folder (in a new tab) #112

Open rsiggi opened 3 years ago

rsiggi commented 3 years ago

It would be nice to have the action

perhaps also in a new or background tab.

RealRaven2000 commented 3 years ago

which folder. a specific folder (specified as selection parameter when defining the filter) or the folder that currently contains the email? Should it highlight the email in that case? and what if the filter matches 50 different emails?

rsiggi commented 3 years ago

a specific folder (specified as selection parameter when defining the filter)

yes

Should it highlight the email in that case?

No

and what if the filter matches 50 different emails?

The folder should only be open onces and not activated if he is open in a background tab.

I see a fast idea and many questions and possibilities. I tag some mails (by filter) from different accounts. Then I have a virtual (local search) folder with all the mails with this tag. If any message gets this tag, then only the folder should be opened. The message does not have to/should not be opened/tagged.

RealRaven2000 commented 3 years ago

a specific folder (specified as selection parameter when defining the filter)

yes

The folder should only be open once and not activated if he is open in a background tab.

thanks for the clarification, I will see what I can do once FiltaQuilla is ported to Thunderbird 91.

kupietools commented 11 months ago

Bump for this. I have an extremely hacky javascript action that does this as a workaround, but it wasn't reliable, and has broken completely as of 115.

What I am trying to do is the functionality Eudora used to have: when new email came into a folder, if that folder wasn't already open in its own window, it was opened in a new window. If it was already open, nothing happened, it stayed open. This way I never, ever missed a new email, and once I had closed all windows, I knew I had seen everything. There's simply no other way around this... I can't rely on unread emails, because sometimes I intentionally leave emails unread for a while, so an unread email and a new email are two different things to me. Whatever other little visual indications people have come up with aren't noticeable enough. I need folders receiving new email to open to ensure they get my attention. I'd love it if FQ did this without me having to write a hacky, unreliable workaround.

(Hint: I've resisted premium because, a professional developer myself, I don't believe in supporting the software "subscription" model where you eventually lose features you have already bought you don't pay for them again annually—even though, yes, your subscription cost is extremely low... it's a principle thing with me. But, this need is great enough for me that I'd make the only exception I've ever made to this belief and subscribe, if this worked well and was a premium feature.)

RealRaven2000 commented 11 months ago

Jeez that's an old thread. I think opening a folder (in Windows) is conceivable, but I really wouldn't have the slightest idea on how to avoid opening a new explorer window, again and again. Even with Thunderbird's illegal super powers (that we still have as experimental Add-on authors) it is hard (and maybe impossible) to look at running processes.

I highly highly recommend installing my Add-on QuickFolders, it's exactly written for this purpose:

image

it shows unread favorite folders in bold and adds a yellow diamond for emails that were received during the current session. It also support showing the status for subfolders of any tab. Just put your most important [parent] folders in the toolbar and you will always see their status at a glance.

kupietools commented 11 months ago

Jeez that's an old thread

Yeah, sorry, but it's an issue near & dear to my heart, and the issue was still open...

I highly highly recommend installing my Add-on QuickFolders, it's exactly written for this purpose

Yeah, tried it. Maybe it's just me, but "at a glance" doesn't work... I have too many folders and it adds up to visual noise that I never notice. I really need windows opened, so I can look at a window, close it, look at the next window, close it, and know I'm done when no other windows are open.

As with so many things, Eudora spoiled me for this for all time. No other email client has worked for me since, until I figured out a hack to do it in TB using FQ, which now is broken in 115.

The way I did this in FQ before now was to have a filter that matched all emails which had a status of "New", which ran the following sloppy javascript hack:

theGlobal = Services.appShell.hiddenDOMWindow;
theGlobal.fqDebug = false;
changeKey = "347";
if (msgHdrs[0].getStringProperty("x-first-folder-URI") == "") {
    msgHdrs[0].setStringProperty("x-first-folder-URI", msgHdrs[0].folder.URI);
    //retrieve for open email from console with gMessageDisplay.displayedMessage.getStringProperty("x-first-folder-URI")
}
if (typeof theGlobal.fqListenerAdded == "undefined" || theGlobal.fqListenerAdded != changeKey) {
    debugwarn = (function(...theLog) {
        if (theGlobal.fqDebug) {
            console.warn(theLog);
        }
    });
    var folderListener = {
        onMessageRemoved: function(parentItem, item) {
        debugwarn("START ------------------------------------------");
            debugwarn("ItemRemoved- parentItem", parentItem.URI,parentItem, "Item", item.author,item.subject,item);
        },
        onMessageAdded: function(parentItem, item) {
            debugwarn("ItemAdded BEGIN - parentItem", parentItem.URI,parentItem, "Item", item.author,item.subject,item);
            draftPropertyIndex = [...item.propertyEnumerator].indexOf("x-mozilla-draft-info");
            debugwarn("OPENER - draft property index", draftPropertyIndex);
            if (draftPropertyIndex == -1) {
                debugwarn("OPENER - starting non-draft (-1) conditional code block");
                  theOpenWins=[];theWins=[...Services.wm.getEnumerator("")];for (i in theWins) { try {theOpenWins.push (theWins[i].GetSelectedMsgFolders()[0].URI);} catch (e) {}};theFound=theOpenWins.some(windowx => windowx==parentItem.URI);
                  debugwarn("theOpenWins",theOpenWins);
                  debugwarn("theWins",theWins);
                  debugwarn("theFound",theFound);
                  if (theFound != true) 
                  {
            //   if (typeof theGlobal.frontmostWindow == "undefined") {
//                    theGlobal.frontmostWindow = {};
               // }
               //don't know why I thought I needed to initialize it...
                theGlobal.frontmostWindow = Services.ww.activeWindow;                

                debugwarn("OPENER - Primary app window is: title", theGlobal.frontmostWindow.location.title, "window object", theGlobal.frontmostWindow,"message string properties are", [...item.propertyEnumerator]);
                let messageURI = {};
                found = undefined;
                debugwarn("OPENER - parentItem (parent folder passed to event handler)", parentItem);
                messageURI.data = parentItem.URI;

                try {
                    Services.wm.getMostRecentWindow("").open("", messageURI.data, "chrome=yes,toolbar=yes,status=yes").close();
                    debugwarn("OPENER - closed ok");
                } 
                catch (openerr) {
                    debugwarn("OPENER - error on close ", openerr);
                }
                debugwarn("OPENER - opening target window");
                newwin = Services.wm.getMostRecentWindow("").openDialog("chrome://messenger/content/messenger.xhtml", messageURI.data, "chrome=yes,toolbar=yes,status=yes", messageURI.data);
                newwin.addEventListener('pageshow', function(e) {
                    theGlobal.frontmostWindow.focus();
                });
                debugwarn("OPENER - opened window - newwin title", newwin.location.title, "newwin object", newwin, "messageURI.data", messageURI.data);
               //newwin.goDoCommand("cmd_toggleMessagePane")
try {
newwin.gMessagePaneWrapper.collapsed=true;}
catch (e)  {
                    debugwarn("OPENER - collapsing message pane failed", e);
                }
                try {
                    theGlobal.frontmostWindow.focus();
                    debugwarn("OPENER - focused", theGlobal.frontmostWindow.document.title, "focused window is now", Services.ww.activeWindow.document.title);
                } 
                catch (e) {
                    debugwarn("OPENER - focus failed", e);
                }
                debugwarn("OPENER - END parentItem", parentItem.URI,parentItem, "item", item.author,item.subject,item);
                debugwarn("END ------------------------------------------");
            } 
                  else
            {
            debugwarn("window already open");
            }         
               }
            else {
                debugwarn("OPENER - skipped folder listener, DRAFT parentItem", parentItem.URI,parentItem, "item", item.author,item.subject,item);
            }
        }
    };
    var notifyFlags = Components.interfaces.nsIFolderListener.added | Components.interfaces.nsIFolderListener.removed;

    MailServices.mailSession.RemoveFolderListener(folderListener);
    MailServices.mailSession.AddFolderListener(folderListener, notifyFlags);
    theGlobal.fqListenerAdded = changeKey;
}

changeKey ensured that the listeners didn't get reattached to the folders every time I edited this while I was working, only when I changed the changekey to indicate the script was ready to go.

The debugwarn steps were just for turning console logging on and off while I was debugging.

It worked ok. It did open duplicate windows, which was a pain, IE if three messages filtered into a folder it opened three windows, if I recall correctly. When I last left off with it earlier this year, I felt like I was close to figuring out how to get it to check a list of which windows were already open and not open duplicates in that case. If I recall correctly, I was thinking about defining a custom property of Services.appShell.hiddenDOMWindow to store an array of folders in as they were opened, which the listeners would clear when they were totally done running, or something, to at least prevent three consecutive window openings from three consecutive emails getting moved in the same session... or something... it's tough to recall, it was a while ago, and it at least worked well enough that it wasn't on top of my list to have to get back to, until this week when it stopped working entirely. I'm sure as a TB developer with one glance you see no-longer-working APIs in it or something.

But, my point is, I was almost all the way there. I feel like it ought to be doable, unless they've changed things so radically that the whole approach just can't work anymore.

Anyway: that's my upvote for this!

RealRaven2000 commented 11 months ago

It's a little late here (Irish timeline) so I couldn't quite parse your code, but it seems you may be opening Thunderbird 3pane windows here and not "file explorer" windows from the OS. I took the liberty of adding javascript syntax to your code snippet.

In that case, it's a little easier because you can investigate the open windows and check their folder URIs. You don't need to keep track, I believe you could enumerate all folder windows and investigate whether the folder is already open and then either do nothing or bring the window to the foreground. (the 1nd choice may be a little disruptive if you get a lot of intermittent traffic on various folders).

Maybe try Services.wm.getEnumerator("mail:3pane") to filter out only folder windows first. Then get the "tabmail" element and look at the first tab to retrieve the folder URI: gTabmail.tabInfo[0].folder.URI by the way you could also open multiple folder tabs in the same window and then iterate them...

kupietools commented 11 months ago

Thanks for the tips... I'm working on debugging this for 115 now. Turns out they renamed message.propertyEnumerator to message.property, so that's one issue fixed, but now it seems like it isn't always receiving the msgHdrs array as expected, so I'm trying to figure out what's wrong there. (LOL, and thanks for tidying my code.)

Yes, I believe you're right about the 3pane windows... but I'm really very unclear on TB's whole structure, with chromeWindows and 3pane windows and invisible windows and stuff. And it was all hacked together a while ago, every time I re-sit down with this I have to figure out again how it works, because it was never that clear in the first place.

I did have another idea, which is to use Terminal-Notifier, which I already call now every time new mail comes in, to open a mailbox by calling the TB executable with -mail and the URI of the mailbox... but, typically, this being Thunderbird, it doesn't always recognize its own imap:// URIs. Sometimes it does, sometimes it doesn't, I haven't figured out the logic of it.

Ireland? Hah, now I have a mental image of you and Turly from FinderPop sitting down in the pub together for a Guinness.

kupietools commented 11 months ago

In case anyone's interested, I got the above script working in TB 115, it's now at https://github.com/kupietools/filtaquilla-open-mail-folder-on-receiving-mail/. It's also updated so it doesn't open duplicate windows anymore if a mailbox is already open in a window. This was pretty easy to do:

//parentItem.URI is the mailbox URI
 theOpenWins = [];
 theWins = [...Services.wm.getEnumerator("")];
 for (i in theWins) {
    if (theWins[i].document.URL == "chrome://messenger/content/messenger.xhtml") {
      theOpenWins.push(theWins[i].GetSelectedMsgFolders()[0].URI);
    }
  };
  theFound = theOpenWins.some(windowx => windowx == parentItem.URI); //returns true if parentItem.URI is already open in a window