Giter Club home page Giter Club logo

Comments (24)

aminomancer avatar aminomancer commented on June 3, 2024

haha that is one crazy looking bug! well, like the readme points out, you definitely can't use every script all at once. also I've recently removed some scripts that were deprecated but still hosted on the repo. so I would suggest deleting all the scripts and then opening firefox and setting up the toolbar the way you want it. then install scripts one by one, just the ones you want. don't just copy the script folder from the repo into your chrome folder. read the scripts section in the readme and check each script individually. for example, for those restorePreProton*Button scripts, there are 2 versions for each, you only want one. but the readme explains all that.

and if there are still problems after you do that, let me know, and open the browser toolbox console and copy and paste everything in it to here. I don't have a macOS machine anymore so I can't easily test this stuff on your OS, and I don't have any collaborators who could really do the kinds of steps I need to go through for debugging. but I don't have any reason to expect such massive incompatibilities, so I think this is more likely caused by the removed scripts, or scripts that are incompatible with each other.

from uc.css.js.

aminomancer avatar aminomancer commented on June 3, 2024

Ok I've just found a mac running 10.15.4 and tested the theme on it. Here are my resultsimage, having installed the entire theme from the latest release package and deleted nothing but the -standalone.uc.js files. So this is running every script (which I don't recommend, and don't do personally, despite having written all of them) with just the few redundant scripts removed. I tried removing the reload button but didn't find any problems. Maybe check if you have minBrowserNavBar.uc.js in your script folder, that will definitely break some things as the script no longer works correctly.

I can see some other more minor problems here though, particularly that there are no window controls and no drag space. I'm working on an update to fix that, but there are other problems here I'm not sure I can support. I can fix most of these issues, but the problem is the macOS and Windows versions of Firefox are substantially different, and I don't use macOS. If I had other contributors to work on compatibility it wouldn't be a big deal, but I barely have enough time to keep up with Firefox Nightly for Windows 10 as it is.

I can fix those CSS problems as they currently exist, but I won't see if any future problems come up and wouldn't have time to deal with them anyway. I have been working on this theme for almost 2 years without even knowing how it looks in macOS haha. So I don't know if I'd recommend using the theme on a mac unless you really know what you're doing and are prepared to fix bugs and adjust things yourself. Most of the scripts should work fine, but Firefox for mac is so intensely different from the other versions that maybe it's better to just use a dedicated macOS theme, or at least a simpler theme that changes fewer things. This theme is really enormous relatively speaking so it's practically guaranteed that it will always have problems in a version it wasn't developed for, at any given time. It's already quite a handful just making something so big work for Windows with twice-daily updates.

I've tried to eliminate all the major usability issues for macOS so if you start over with the latest updates I think you'll find it's usable. Download the zip with the green code button, not from a release package. But if you're picky about little things like margins, you might need to make some changes as you go, and as Firefox is updated, since I don't have any plans to make this macOS debugging a regular thing. It's just too time-consuming to get my whole development suite set up on a mac. I am probably open to outside contributions though, so that might come in the future.

edit: btw, if you try the update, I'd appreciate if you could let me know which side (left or right) the titlebar buttons appear on for you. Like normally on macOS the close/min/max buttons appear on the left side. But for some reason while I was testing on that mac, the titlebar buttons were on the right. I figure that's something I should fix with CSS but first I wanna know if it's like that for everyone, and whether people actually want the buttons on the left.

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

Thanks for the update! I'll definitely try the new version out. Will post an update here.

After posting this issue, I did exactly what you described here - starting from fresh and only adding scripts I need. This seems to work a lot better since I only added the scripts you mentioned in your README (those of your masterpieces XD), excluding things like minBrowserNavBar.uc.js. After all, I plan to integrate your scripts into my own theme anyways.

That being said, I can definitely help if you need to test on macOS. I set up a clean macOS virtual machine just to try out your theme. Again, great work!

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

This is how the window looks like after starting out fresh and using the latest version (removing the non--standalone.uc.js scripts if there is any).

image

The titlebar buttons show up on the left side for me. I do want those button to show on the left side since it's compatible with the whole OS. But having an option for left/right would definitely be nice. Though the size of the buttons is quite large, here's a comparison with a normal finder window:

image

Oh, and the max and close buttons are swapped... I haven't look into the css code yet but I suppose this and the size issue can be fixed there.

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

I came across three bugs (not sure if those exists in other OS's):

  1. On the new page, the bookmark bar is supposed to show up when the mouse hovers in the navbar area. However, only after I specifically click in the urlbar (clicking on the navbar doesn't help) will the bookmark bar behave correctly.
  2. The debug extension context menu simply doesn't work. The menu items are all there but they seem to do nothing - copy ID, view source, etc. all don't do anything.
  3. Open bookmark in a container doesn't work - it doesn't do anything. However, right-click on the tab and select "Open in Container Tab" does work.

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

Two more things:

  1. The green titlebar button maximizes the window. Though, in macOS, the green button triggers the full-screen action. (Yes, there's no actual max button in macOS, hilarious...) Not sure if it's better to make it comply with the OS or not.
  2. Under full-screen mode, the entire navbar (tabbar+urlbar) does not always come up when cursor reaches the top edge of the screen. It does show up every other time, but not every time. See the demo below.

screenshot

from uc.css.js.

aminomancer avatar aminomancer commented on June 3, 2024

Yeah the titlebar buttons are designed to make windows 10's buttons look similar to macOS buttons. The order of the buttons is different on macOS so I had to change the order to make them look right. I added a new script osDetector.uc.js that makes an attribute on the root element, like :root[operatingsystem="macosx"] so that can be used to isolate the titlebar button rules to just windows. I don't really have the energy to deal with that right now but it's simple enough to fix. The rules are in uc-tabs-bar.css

As for your other problems,

  1. Unless I misunderstood, that's the expected behavior. The bookmarks bar is not supposed to show up when the mouse hovers in the navbar area if the urlbar is focused/open. Otherwise the two get in the way of each other and look silly. The bookmarks bar can't be meaningfully interacted with while the urlbar is open anyway. That script autoHideNavbarSupport.uc.js is designed to hide the bookmarks bar while the urlbar is focused. Since the urlbar is automatically focused when you open a new tab, the bookmarks bar starts hidden until you deselect the urlbar. This whole feature can be disabled by uninstalling that script though. It already has a more severe problem on macOS — in fullscreen, the macOS menubar already automatically hides. So they get in the way of each other. You mouse up to the top and they both appear but with a different delay. It makes it very hard to use. So I would just disable that altogether if I were you.

2 and 3 seem to be manifestations of the same problem. Some fundamental difference in the way menuitems work on macOS. For one, you need to enable native context menus. I don't know how to make user.js select based on operating system so you just need to set that pref yourself, widget.macos.native-context-menus needs to be false.

And of course, "Open in Container Tab" is not from any script I made. That's built into firefox, which is probably why it works.

Aside from that, like I mentioned before, I didn't write a single line of code for macOS so it's not realistic that every file on this repo is gonna be compatible with macOS. I'm actually surprised it works as well as it does, considering the huge differences between the versions of Firefox. I think it would take someone who uses macOS full time to debug all of this and I just can't make that commitment, as this project is purely a hobby for me, and I don't even own a mac.

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

I can confirm that seeting widget.macos.native-context-menus to false fixes the problem 2 and 3. The only other problem I have found is the 'Toggle tabs and sidebar' button. It does closes the sidebar, but it doesn't toggle the tabs. So now it functions like a sidebar open/close button.

As for the titlebar button, I can fix it myself since you offer the osDetector.uc.js script. Thanks a lot!!

from uc.css.js.

aminomancer avatar aminomancer commented on June 3, 2024

yeah it's not supposed to toggle the tabs. it says in the description that's not what it does:

it hides tabs by setting an attribute on the document element, which you need to reference in your userChrome.css file, like this: :root[toggle-hidden="tabs"] #TabsToolbar {...}. There are various templates available online for hiding the tab bar, or you can ask on /r/FirefoxCSS. Just use one of those, adding :root[toggle-hidden="tabs"] to the selectors.

it was made for a request on reddit. I just figured it was a common request so I posted it on here too. the person who asked me to make it already had their own way of hiding tabs. so the script just does the hard part, it's up to the user to make the accompanying CSS to their own preferences. as for me, I don't hide tabs at all, not what the theme was designed for. that's why there's not an asterisk next to the script.

and yeah at a glance it looks like the regular sidebar button, but it does more under the hood too, if you read the script description. the regular sidebar button can't hide the tabs, because the tabs are in a totally different part of the DOM. they can't know when the sidebar is open or closed. not without setting attributes or something much higher up in the DOM hierarchy. that's the main thing the script is for, it's similar to autoHideNavbarSupport in that all it does is set markup attributes, it's the CSS that has to use them. but the person who requested it wanted that feature to be a separate button, not just a modification to the built-in sidebar button. so I just made a new button.

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

Thanks! I managed to make it work with my CSS. Here's a minor question (thought I'd just ask here instead of opening a new issue): where is the restart button mentioned in the appMenuMods.uc.js? I do see other changes it does (i.e., changing "Add-ons and Themes" to "Extensions" and adding a separator under the "Manage Account" button), but just not the restart button. I am using the fx-autoconfig by MrOtherGuy as you recommended.

from uc.css.js.

aminomancer avatar aminomancer commented on June 3, 2024

you have version 1.2? maybe you need to update the script, I only added the restart button to the script 4 days ago.

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

Yes, version 1.2. In fact, I just re-downloaded your latest zip (from git clone) but I still don't see the button, though I do see the addRestartButton(strings) function which gets called in handleEvent(_e).

from uc.css.js.

aminomancer avatar aminomancer commented on June 3, 2024

oh, I see the issue. on macOS for some reason there's no exit button. since the restart button is supposed to be placed right above the exit button, the function stops on exception and the restart button never gets placed in the document. anyway try version 1.3

keep in mind I have no idea if fx-autoconfig's restart function actually works on macOS. the fact that the exit button is removed seems to imply that there might be some problem with firefox's ability to control its processes internally on macOS. the button might just do nothing. but it's worth a try at least

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

It works! Thanks so much! By the way, if I want to add my own CSS style, can I simply put it after all the imports in userChrome.css? The reason I ask is that I want to make the bookmark bar item centered. #PlacesToolbarItems { -moz-box-pack: center; } used to work perfectly for me. But now it doesn't. I wonder if it has to do with the order of imports.

from uc.css.js.

aminomancer avatar aminomancer commented on June 3, 2024

yeah you can add CSS any way you want. userChrome.css doesn't come with an extra import rule for custom sheets because if the user doesn't have one (like I don't) the browser console reports an error about the sheet being missing. but yeah an import rule at the end of userChrome.css will come last in the load order so it'll override everything before it (of equal specificity) of course.

you can also make a script that uses the stylesheet service to load a stylesheet, if you want an author sheet or agent sheet. actually, you can load a user sheet that way too. normally there wouldn't be much point, but if you did it that way you wouldn't have to worry about overwriting userChrome.css when you update the theme. but I'll leave that up to your discretion.

as for centering bookmark items, I don't think that's anything my theme does. you can't center the bookmark items that way because the container doesn't have a fixed width. it's only as wide as the bookmarks inside it. so the alignment has no effect at all, right, left, or center, it's all the same since there's no empty space at all. you can change that several ways. I think this is best:

#PersonalToolbar {
    justify-content: center !important;
}

I think that's best because there can be other elements in there besides just the bookmark items. you don't want the other elements to be left-aligned and have the bookmarks way off on their own in the center, that'd look weird. normally you only see bookmarks there, but there's the chevron button when overflowing, the bookmarks toolbar button when customizing, and the empty toolbar placeholder.

but, that said, you can also do this:

#PlacesToolbarItems {
    -moz-box-pack: center;
}
#personal-bookmarks {
    width: -moz-available;
}

from uc.css.js.

aminomancer avatar aminomancer commented on June 3, 2024

I like your avatar btw. is that seal script?

from uc.css.js.

aminomancer avatar aminomancer commented on June 3, 2024

I should probably clarify, this theme isn't really designed for use with the bookmarks toolbar. I don't use the toolbar personally so I developed the whole theme with it disabled altogether. it wasn't until I started publishing the theme that I decided to work on the bookmarks toolbar. so it has some major deficiencies that I can't really solve without adding another pretty complicated script.

the issue stems from the fact that I moved the findbar to the top of the browser area, and changed how the fullscreen navbar auto-hide feature works. I made the whole navbar float over the content rather than flexing it. which is still a change I stand by since I think the flexing animation is very jarring otherwise. but it means the size and margins of everything at that level need to be fixed.

and having done all that, I figured I'd do the same with the bookmarks bar in all modes, since I rarely use it and didn't want it taking up so much vertical space. but the thing is, there are other elements under the bookmarks bar, they just rarely appear. since proton, that's where tab notifications appear. mainly plugin crash notifications but ostensibly, any kind of notification could be drawn there.

basically, it expects the navbar to be equal to the height of the navbar plus the height of the tab bar. adding the bookmarks bar to that messes everything up. there aren't any attributes to tell us when the bookmarks bar is visible or not, so we can't adjust those rules to fit. which means when a notification appears while the bookmarks bar is open, the notification ends up being drawn behind the bookmarks bar. which is a big problem since hovering the notification counts as hovering the nav toolbox, which causes the bookmarks bar to expand. meaning notifications are unclickable while the bookmarks bar is open hahaha. it's quite a catch 22.

I decided to simply hide the notification bar while the bookmarks bar is open but this isn't great. firefox already hides the bookmarks bar in fullscreen mode for similar reasons. and in my case that's good since it'd cause the findbar to be drawn behind the bookmarks bar in fullscreen too.

there might be some ways I could still improve this, and I'll look into that over the next month or so, but generally it just means that this isn't a great setup for someone who uses the bookmarks toolbar a lot. as you can see from the screenshots, it's pretty much designed for use with the bookmarks bar disabled. I just use the bookmarks menu button and sidebar instead.

that said, you could change the way this works. I might make a preference that does exactly that, disables the bookmarks bar auto-hide feature. but in the meantime, you could override the rules in uc-navbar.css that auto-hide the toolbar, and if you wanted to use the bookmarks bar in fullscreen for whatever reason, you could adjust the margins of the findbar and browser content area in uc-fullscreen.css, and make a rule like #PersonalToolbar {visibility: visible !important;} since that's how firefox hides it in fullscreen mode.

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

yeah you can add CSS any way you want. userChrome.css doesn't come with an extra import rule for custom sheets because if the user doesn't have one (like I don't) the browser console reports an error about the sheet being missing. but yeah an import rule at the end of userChrome.css will come last in the load order so it'll override everything before it (of equal specificity) of course.

you can also make a script that uses the stylesheet service to load a stylesheet, if you want an author sheet or agent sheet. actually, you can load a user sheet that way too. normally there wouldn't be much point, but if you did it that way you wouldn't have to worry about overwriting userChrome.css when you update the theme. but I'll leave that up to your discretion.

as for centering bookmark items, I don't think that's anything my theme does. you can't center the bookmark items that way because the container doesn't have a fixed width. it's only as wide as the bookmarks inside it. so the alignment has no effect at all, right, left, or center, it's all the same since there's no empty space at all. you can change that several ways. I think this is best:

#PersonalToolbar {
    justify-content: center !important;
}

I think that's best because there can be other elements in there besides just the bookmark items. you don't want the other elements to be left-aligned and have the bookmarks way off on their own in the center, that'd look weird. normally you only see bookmarks there, but there's the chevron button when overflowing, the bookmarks toolbar button when customizing, and the empty toolbar placeholder.

but, that said, you can also do this:

#PlacesToolbarItems {
    -moz-box-pack: center;
}
#personal-bookmarks {
    width: -moz-available;
}

Thanks! This works like a charm! I'll look into writing a script haha!

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

I like your avatar btw. is that seal script?

Thanks, glad you like it! Yes, that is the seal script! I made this avatar way back in high school... It's been a long time!

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

I see your point. I only use the bookmark bar when on new page; other times I don't want to see it so that I can see more of the webpage itself.

The theme I'm trying to make is one that's very close to the original theme, with a few tweaks like some of your masterpiece scripts, and the Lepton fix (you've already incorporated it so maybe a bit less work for me haha). This way I can use all the themes online, even light color ones. Maybe a better way for me to do is, instead of subtracting things from your theme, I should probably try starting from the original state and add things to it. So far my theme looks like this:

image

And in light theme:

image

But I only have like 1% of the firefox knowledge you have so it might be a bit hard for me to do all of those, haha!

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

Oh, as you can see from the screenshot above, since I hide the tabbar, I'd like the Open in private tab button to be pinned to the navbar. But it always goes back to the tabbar after restart, making it inaccessible in my theme. Is there something in the script I can change so that it stays in the navbar? Or better yet, is it possible that this button can also appear in the vertical bar from your script?

from uc.css.js.

aminomancer avatar aminomancer commented on June 3, 2024

The private tabs script creates multiple buttons that are designed to mirror the position of the new tab button. In firefox there are 2 new tab buttons. One that is right next to the last tab, and one that appears next to the tab strip itself when the tab strip is overflowing. The reasoning for that is complicated but naturally the script wants to emulate that overflow/underflow behavior. So there are 2 private tab buttons. But you can try this to eliminate all that and make just one button, for the navbar.

// ==UserScript==
// @name           Private Tabs
// @version        1.1 (Custom toolbar button version)
// @author         aminomancer
// @homepage       https://github.com/aminomancer
// @description    An fx-autoconfig port of Private Tab by xiaoxiaoflood. Adds buttons and menu items allowing you to open a "private tab" in nearly any circumstance in which you'd be able to open a normal tab. Instead of opening a link in a private window, you can open it in a private tab instead. This will use a special container and prevent history storage, depending on user configuration. You can also toggle tabs back and forth between private and normal mode. This script adds two hotkeys: Ctrl+alt+P to open a new private tab, and ctrl+alt+T to toggle private mode for the active tab. These hotkeys can be configured along with several other options at the top of the script file.
// @include        main
// @include        chrome://browser/content/places/bookmarksSidebar.xhtml
// @include        chrome://browser/content/places/historySidebar.xhtml
// @include        chrome://browser/content/places/places.xhtml
// ==/UserScript==

class PrivateTabManager {
    constructor() {
        if (!_ucUtils.sharedGlobal.privateTabGlobal) _ucUtils.sharedGlobal.privateTabGlobal = {};
        let privateTabGlobal = _ucUtils.sharedGlobal.privateTabGlobal;
        this.config = {
            neverClearData: false, // if you want to not record history but don't care about other data, maybe even want to keep private logins
            restoreTabsOnRestart: true,
            doNotClearDataUntilFxIsClosed: true,
            deleteContainerOnDisable: false,
            clearDataOnDisable: false,
            toggleHotkey: "T", // key for toggling private mode for the active tab. ctrl + alt + T by default.
            newTabHotkey: "P", // key for opening a new private tab. ctrl + alt + P by default.
            toggleModifiers: "alt accel", // modifiers for toggle hotkey. this means alt+ctrl on windows or alt+cmd on mac
            newTabModifiers: "alt accel", // modifiers for new tab hotkey.
        };
        // isn't strictly necessary, but due to a programmer's oversight, this seems to be the only way to prevent irritating animations when toggling private mode on/off for a tab. what's actually happening under the hood is not a simple state change, since that would be insecure. the whole point of all this is to avoid leaking information, so when we turn private mode on, we need to create a brand new tab and restore it from cached data. but the internal duplicateTab method doesn't pass the skipAnimation parameter to addTrustedTab. so we need to make our own function, which requires these unexposed modules.
        let { SessionStoreInternal } = Cu.import(
            "resource:///modules/sessionstore/SessionStore.jsm"
        );
        this.SSI = SessionStoreInternal;
        XPCOMUtils.defineLazyModuleGetters(this, {
            TabState: "resource:///modules/sessionstore/TabState.jsm",
            TabStateFlusher: "resource:///modules/sessionstore/TabStateFlusher.jsm",
        });
        this.sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(
            Ci.nsIStyleSheetService
        );
        privateTabGlobal.openTabs = new Set();
        if (typeof window.gProton != "undefined") privateTabGlobal.gProton = window.gProton;
        this.menuClass = privateTabGlobal.gProton ? `` : `menuitem-iconic privatetab-icon`;
        this.openTabs = privateTabGlobal.openTabs;
        this.orig_getAttribute = MozElements.MozTab.prototype.getAttribute;
        this.BTN_ID = "privateTab-button";
        this.BTN2_ID = "newPrivateTab-button";
        this.init();
        if (location.href != "chrome://browser/content/browser.xhtml") return this.exec();
        if (gBrowserInit.delayedStartupFinished) this.exec();
        else {
            let delayedListener = (subject, topic) => {
                if (topic == "browser-delayed-startup-finished" && subject == window) {
                    Services.obs.removeObserver(delayedListener, topic);
                    this.exec();
                }
            };
            Services.obs.addObserver(delayedListener, "browser-delayed-startup-finished");
        }
    }

    exec() {
        let privateTabGlobal = _ucUtils.sharedGlobal.privateTabGlobal;
        if (PrivateBrowsingUtils.isWindowPrivate(window)) return;
        let openAll = document.getElementById("placesContext_openBookmarkContainer:tabs");
        let openAllPrivate = _ucUtils.createElement(document, "menuitem", {
            id: "openAllPrivate",
            label: "Open All in Private Tabs",
            accesskey: "v",
            class: this.menuClass,
            oncommand: `event.userContextId = ${
                this.container.userContextId
            }; ${openAll.getAttribute("oncommand")}`,
            onclick: `event.userContextId = ${this.container.userContextId}; ${openAll.getAttribute(
                "onclick"
            )}`,
        });
        openAll.after(openAllPrivate);

        let openAllLinks = document.getElementById("placesContext_openLinks:tabs");
        let openAllLinksPrivate = _ucUtils.createElement(document, "menuitem", {
            id: "openAllLinksPrivate",
            label: "Open All in Private Tabs",
            accesskey: "v",
            class: this.menuClass,
            oncommand: `event.userContextId = ${
                this.container.userContextId
            }; ${openAllLinks.getAttribute("oncommand")}`,
            onclick: `event.userContextId = ${
                this.container.userContextId
            }; ${openAllLinks.getAttribute("onclick")}`,
        });
        openAllLinks.after(openAllLinksPrivate);

        let openTab = document.getElementById("placesContext_open:newtab");
        let openPrivate = _ucUtils.createElement(document, "menuitem", {
            id: "openPrivate",
            label: "Open in a New Private Tab",
            accesskey: "v",
            class: this.menuClass,
            oncommand: `let view = event.target.parentElement._view; PlacesUIUtils._openNodeIn(view.selectedNode, "tab", view.ownerWindow, false, ${this.container.userContextId})`,
        });
        openTab.after(openPrivate);

        document.getElementById("placesContext").addEventListener("popupshowing", this);

        if (location.href != "chrome://browser/content/browser.xhtml") return;

        let keyset = _ucUtils.createElement(document, "keyset", { id: "privateTab-keyset" });
        document.getElementById("mainKeyset").after(keyset);

        let toggleKey = _ucUtils.createElement(document, "key", {
            id: "togglePrivateTab-key",
            modifiers: this.config.toggleModifiers,
            key: this.config.toggleHotkey,
            oncommand: "privateTab.togglePrivate()",
        });
        keyset.appendChild(toggleKey);

        let newPrivateTabKey = _ucUtils.createElement(document, "key", {
            id: "newPrivateTab-key",
            modifiers: this.config.newTabModifiers,
            key: this.config.newTabHotkey,
            oncommand: "privateTab.BrowserOpenTabPrivate()",
        });
        keyset.appendChild(newPrivateTabKey);

        let menuOpenLink = _ucUtils.createElement(document, "menuitem", {
            id: "menu_newPrivateTab",
            label: "New Private Tab",
            accesskey: "v",
            acceltext: ShortcutUtils.prettifyShortcut(newPrivateTabKey),
            class: this.menuClass,
            oncommand: "privateTab.BrowserOpenTabPrivate()",
        });
        document.getElementById("menu_newNavigatorTab").after(menuOpenLink);

        let openLink = _ucUtils.createElement(document, "menuitem", {
            id: "openLinkInPrivateTab",
            label: "Open Link in New Private Tab",
            accesskey: "v",
            class: this.menuClass,
            hidden: true,
            oncommand: `openLinkIn(gContextMenu.linkURL, "tab", gContextMenu._openLinkInParameters({ userContextId: privateTab.container.userContextId, triggeringPrincipal: document.nodePrincipal, }));`,
        });

        document.getElementById("contentAreaContextMenu").addEventListener("popupshowing", this);
        document.getElementById("contentAreaContextMenu").addEventListener("popuphidden", this);
        document.getElementById("context-openlinkintab").after(openLink);

        let toggleTab = _ucUtils.createElement(document, "menuitem", {
            id: "toggleTabPrivateState",
            label: "Private Tab",
            type: "checkbox",
            accesskey: "v",
            acceltext: ShortcutUtils.prettifyShortcut(toggleKey),
            oncommand: "privateTab.togglePrivate(TabContextMenu.contextTab)",
        });
        document.getElementById("context_pinTab").after(toggleTab);
        document.getElementById("tabContextMenu").addEventListener("popupshowing", this);

        let privateMask = document.getElementsByClassName("private-browsing-indicator")[0];
        privateMask.id = "private-mask";

        gBrowser.tabContainer.addEventListener("TabSelect", this);

        addEventListener("XULFrameLoaderCreated", this);

        if (this.observePrivateTabs) gBrowser.tabContainer.addEventListener("TabClose", this);

        MozElements.MozTab.prototype.getAttribute = function (att) {
            if (att == "usercontextid" && this.isToggling) {
                delete this.isToggling;
                return privateTab.orig_getAttribute.call(this, att)
                    ? 0
                    : privateTab.container.userContextId;
            } else return privateTab.orig_getAttribute.call(this, att);
        };

        if (!privateTabGlobal.privateTabsInited)
            CustomizableUI.createWidget({
                id: this.BTN_ID,
                type: "custom",
                defaultArea: CustomizableUI.AREA_NAVBAR,
                showInPrivateBrowsing: false,
                onBuild: (doc) => {
                    let btn = _ucUtils.createElement(doc, "toolbarbutton", {
                        id: this.BTN_ID,
                        label: "New Private Tab",
                        tooltiptext: `Open a new private tab (${ShortcutUtils.prettifyShortcut(
                            newPrivateTabKey
                        )})`,
                        class: "toolbarbutton-1 chromeclass-toolbar-additional",
                        oncommand: "privateTab.BrowserOpenTabPrivate()",
                    });

                    return btn;
                },
            });
        privateTabGlobal.privateTabsInited = true;
    }

    init() {
        let privateTabGlobal = _ucUtils.sharedGlobal.privateTabGlobal;
        ContextualIdentityService.ensureDataReady();
        this.container = ContextualIdentityService._identities.find(
            (container) => container.name == "Private"
        );
        if (!this.container) {
            ContextualIdentityService.create("Private", "fingerprint", "purple");
            this.container = ContextualIdentityService._identities.find(
                (container) => container.name == "Private"
            );
        } else if (!this.config.neverClearData) {
            this.clearData();
        }

        this.setStyle();
        this.sss.loadAndRegisterSheet(this.STYLE.url, this.STYLE.type);

        if (!privateTabGlobal.privateTabsInited) {
            let { getBrowserWindow } = Cu.import("resource:///modules/PlacesUIUtils.jsm");
            let openTabsetString = PlacesUIUtils.openTabset.toString();
            eval(
                `PlacesUIUtils.openTabset = ${
                    openTabsetString.startsWith("function") ? "" : "function "
                }` +
                    openTabsetString.replace(
                        /(\s+)(inBackground: loadInBackground,)/,
                        "$1$2$1userContextId: aEvent.userContextId || 0,"
                    )
            );

            eval(
                "PlacesUIUtils._openNodeIn = " +
                    PlacesUIUtils._openNodeIn
                        .toString()
                        .replace(/(\s+)(aPrivate = false)\n/, "$1$2,$1userContextId = 0\n")
                        .replace(/(\s+)(private: aPrivate,)\n/, "$1$2$1userContextId,\n")
            );
        }

        let { UUIDMap } = Cu.import("resource://gre/modules/Extension.jsm");
        let TST_ID = "[email protected]";
        this.TST_UUID = UUIDMap.get(TST_ID, false);

        if (this.TST_UUID) this.setTstStyle(this.TST_UUID);
        if (AddonManager && location.href === "chrome://browser/content/browser.xhtml")
            AddonManager.addAddonListener({
                onInstalled: (addon) => {
                    if (addon.id == TST_ID) this.setTstStyle(UUIDMap.get(TST_ID, false));
                },
                onUninstalled: (addon) => {
                    if (addon.id == TST_ID)
                        this.sss.unregisterSheet(this.TST_STYLE.url, this.TST_STYLE.type);
                },
            });

        if (!this.config.neverClearData) {
            Services.obs.addObserver(this, "quit-application-granted");
        }
    }

    observe(sub, top, data) {
        this.clearData();
        if (!this.config.restoreTabsOnRestart) this.closeTabs();
    }

    clearData() {
        Services.clearData.deleteDataFromOriginAttributesPattern({
            userContextId: this.container.userContextId,
        });
    }

    closeTabs() {
        ContextualIdentityService._forEachContainerTab((tab, tabbrowser) => {
            if (tab.userContextId == this.container.userContextId) tabbrowser.removeTab(tab);
        });
    }

    duplicateTab(tab, { index, inBackground }) {
        // Create a new tab.
        let userContextId = tab.getAttribute("usercontextid");

        let tabOptions = {
            userContextId,
            index,
            skipAnimation: true,
            ...(tab == gBrowser.selectedTab ? { relatedToCurrent: true, ownerTab: tab } : {}),
        };
        let newTab = gBrowser.addTrustedTab(null, tabOptions);

        // Start the throbber to pretend we're doing something while actually
        // waiting for data from the frame script. This throbber is disabled
        // if the URI is a local about: URI.
        let uriObj = tab.linkedBrowser.currentURI;
        if (!uriObj || (uriObj && !uriObj.schemeIs("about"))) {
            newTab.setAttribute("busy", "true");
        }

        // Hack to ensure that the about:home, about:newtab, and about:welcome
        // favicon is loaded instantaneously, to avoid flickering and improve
        // perceived performance.
        gBrowser.setDefaultIcon(newTab, uriObj);

        // Collect state before flushing.
        let tabState = this.TabState.collect(tab, SessionStore.getCustomTabValue(tab));

        // Flush to get the latest tab state to duplicate.
        let browser = tab.linkedBrowser;
        this.TabStateFlusher.flush(browser).then(() => {
            // The new tab might have been closed in the meantime.
            if (newTab.closing || !newTab.linkedBrowser) return;

            let window = newTab.ownerGlobal;

            // The tab or its window might be gone.
            if (!window || !window.__SSi) return;

            // Update state with flushed data. We can't use TabState.clone() here as
            // the tab to duplicate may have already been closed. In that case we
            // only have access to the <xul:browser>.
            let options = { includePrivateData: true };
            this.TabState.copyFromCache(browser.permanentKey, tabState, options);

            tabState.index += 0;
            tabState.index = Math.max(1, Math.min(tabState.index, tabState.entries.length));
            tabState.pinned = false;

            if (!inBackground) gBrowser.selectedTab = newTab;

            // Restore the state into the new tab.
            this.SSI.restoreTab(newTab, tabState, {
                restoreImmediately: true,
            });
        });

        return newTab;
    }

    togglePrivate(tab = gBrowser.selectedTab) {
        tab.isToggling = true;
        let shouldSelect = tab == gBrowser.selectedTab;
        let newTab = this.duplicateTab(tab, {
            index: shouldSelect ? tab._tPos + 1 : tab._tPos,
            inBackground: !shouldSelect,
        });
        if (shouldSelect) if (gURLBar.focused) gURLBar.focus();
        gBrowser.removeTab(tab, { animate: false, closeWindowWithLastTab: false });
    }

    toggleMask() {
        let privateMask = document.getElementById("private-mask");
        if (gBrowser.selectedTab.isToggling)
            privateMask.setAttribute(
                "enabled",
                gBrowser.selectedTab.userContextId == this.container.userContextId
                    ? "false"
                    : "true"
            );
        else
            privateMask.setAttribute(
                "enabled",
                gBrowser.selectedTab.userContextId == this.container.userContextId
                    ? "true"
                    : "false"
            );
    }

    BrowserOpenTabPrivate() {
        openTrustedLinkIn(BROWSER_NEW_TAB_URL, "tab", {
            userContextId: this.container.userContextId,
        });
    }

    isPrivate(tab) {
        return tab.getAttribute("usercontextid") == this.container.userContextId;
    }

    contentContext(_e) {
        let tab = gBrowser.getTabForBrowser(gContextMenu.browser);
        gContextMenu.showItem(
            "openLinkInPrivateTab",
            gContextMenu.onSaveableLink || gContextMenu.onPlainTextLink
        );
        if (this.isPrivate(tab)) gContextMenu.showItem("context-openlinkincontainertab", false);
    }

    hideContext(_e) {
        document.getElementById("openLinkInPrivateTab").hidden = true;
    }

    tabContext(_e) {
        document
            .getElementById("toggleTabPrivateState")
            .setAttribute(
                "checked",
                TabContextMenu.contextTab.userContextId == this.container.userContextId
            );
    }

    placesContext(_e) {
        document.getElementById("openPrivate").disabled = document.getElementById(
            "placesContext_open:newtab"
        ).disabled;
        document.getElementById("openPrivate").hidden = document.getElementById(
            "placesContext_open:newtab"
        ).hidden;
        document.getElementById("openAllPrivate").disabled = document.getElementById(
            "placesContext_openBookmarkContainer:tabs"
        ).disabled;
        document.getElementById("openAllPrivate").hidden = document.getElementById(
            "placesContext_openBookmarkContainer:tabs"
        ).hidden;
        document.getElementById("openAllLinksPrivate").disabled = document.getElementById(
            "placesContext_openLinks:tabs"
        ).disabled;
        document.getElementById("openAllLinksPrivate").hidden = document.getElementById(
            "placesContext_openLinks:tabs"
        ).hidden;
    }

    handleEvent(e) {
        switch (e.type) {
            case "TabSelect":
                this.onTabSelect(e);
                break;
            case "TabClose":
                this.onTabClose(e);
                break;
            case "XULFrameLoaderCreated":
                this.privateListener(e);
                break;
            case "popupshowing":
                if (e.target === document.getElementById("placesContext")) this.placesContext(e);
                if (e.target === document.getElementById("contentAreaContextMenu"))
                    this.contentContext(e);
                if (e.target === document.getElementById("tabContextMenu")) this.tabContext(e);
                break;
            case "popuphidden":
                if (e.target === document.getElementById("contentAreaContextMenu"))
                    this.hideContext(e);
                break;
            case "click":
                if (e.button == 0) this.BrowserOpenTabPrivate();
                else if (e.button == 2) {
                    document.popupNode = document.getElementById(this.BTN_ID);
                    document
                        .getElementById("toolbar-context-menu")
                        .openPopup(this, "after_start", 14, -10, false, false);
                    document.getElementsByClassName(
                        "customize-context-removeFromToolbar"
                    )[0].disabled = false;
                    document.getElementsByClassName(
                        "customize-context-moveToPanel"
                    )[0].disabled = false;
                    e.preventDefault();
                }
                break;
        }
    }

    privateListener(e) {
        let browser = e.target;
        let tab = gBrowser.getTabForBrowser(browser);
        if (!tab) return;
        let isPrivate = this.isPrivate(tab);

        if (!isPrivate) {
            if (this.observePrivateTabs) {
                this.openTabs.delete(tab);
                if (!this.openTabs.size) this.clearData();
            }
            return;
        }

        if (this.observePrivateTabs) this.openTabs.add(tab);

        browser.browsingContext.useGlobalHistory = false;
    }

    onTabSelect(e) {
        if (e.target.userContextId != e.detail.previousTab.userContextId) this.toggleMask();
    }

    onTabClose(e) {
        if (this.isPrivate(e.target)) {
            this.openTabs.delete(e.target);
            if (!this.openTabs.size) this.clearData();
        }
    }

    get observePrivateTabs() {
        return (
            this._observePrivateTabs ||
            (this._observePrivateTabs =
                !this.config.neverClearData && !this.config.doNotClearDataUntilFxIsClosed)
        );
    }

    setStyle() {
        this.STYLE = {
            url: Services.io.newURI(
                "data:text/css;charset=UTF-8," +
                    encodeURIComponent(
                        `.privatetab-icon, #${this.BTN_ID}, #${this.BTN2_ID} { list-style-image: url(chrome://browser/skin/privateBrowsing.svg) !important; fill: currentColor; -moz-context-properties: fill; } @-moz-document url('chrome://browser/content/browser.xhtml') { #private-mask[enabled="true"] { display: block !important; } #tabbrowser-tabs[hasadjacentnewprivatetabbutton]:not([overflow="true"]) ~ #${this.BTN_ID}, #tabbrowser-tabs[overflow="true"] > #tabbrowser-arrowscrollbox > #${this.BTN2_ID}, #tabbrowser-tabs:not([hasadjacentnewprivatetabbutton]) > #tabbrowser-arrowscrollbox > #${this.BTN2_ID}, #TabsToolbar[customizing="true"] #${this.BTN2_ID} { display: none; } .tabbrowser-tab[usercontextid="${this.container.userContextId}"] .tab-label { text-decoration: underline !important; text-decoration-color: -moz-nativehyperlinktext !important; text-decoration-style: dashed !important; } .tabbrowser-tab[usercontextid="${this.container.userContextId}"][pinned] .tab-icon-image, .tabbrowser-tab[usercontextid="${this.container.userContextId}"][pinned] .tab-throbber { border-bottom: 1px dashed -moz-nativehyperlinktext !important; }}`
                    )
            ),
            type: this.sss.USER_SHEET,
        };
    }

    setTstStyle(uuid) {
        this.TST_STYLE = {
            url: Services.io.newURI(
                "data:text/css;charset=UTF-8," +
                    encodeURIComponent(
                        `@-moz-document url-prefix(moz-extension://${uuid}/sidebar/sidebar.html) { .tab.contextual-identity-firefox-container-${this.container.userContextId} .label-content { text-decoration: underline !important; text-decoration-color: -moz-nativehyperlinktext !important; text-decoration-style: dashed !important; } .tab.contextual-identity-firefox-container-${this.container.userContextId} tab-favicon { border-bottom: 1px dashed -moz-nativehyperlinktext !important;}}`
                    )
            ),
            type: this.sss.USER_SHEET,
        };
        this.sss.loadAndRegisterSheet(this.TST_STYLE.url, this.TST_STYLE.type);
    }
}

window.privateTab = new PrivateTabManager();

Thanks for letting me know about this, btw. I don't use this script myself, so I hadn't noticed that the toggle function has been broken in Nightly since June 26. A lot of these scripts were just requests, for which I didn't have enough time to follow up on and maintain consistently. But now I've fixed that bug too so thanks

from uc.css.js.

aminomancer avatar aminomancer commented on June 3, 2024

And very cool, that's awesome. Wish I could read it lol. Ancient Chinese history is so fascinating, I have been studying the Chu kingdom lately ever since I bought this insanely long heavy cavalry sword replica. Their visual art style was so unique and "modern," I've been trying to emulate the shapes in my graphic design work lately.

from uc.css.js.

henryxrl avatar henryxrl commented on June 3, 2024

The private tabs toolbar button works like a charm! Thank you for the modified script!
I have also modified the toggle tabs and sidebar script so that it toggles the tabs on and off only. :-D

Ancient Chinese history is indeed fascinating! That roaring dragon sword looks amazing! Can't wait to see your graphic design work, if possible!

from uc.css.js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.