material-extensions / material-icons-browser-extension

Browser Addon that enhances file browsers of version controls with material icons.
MIT License
511 stars 38 forks source link

Add support for Azure DevOps and BitBucket #31

Closed csandman closed 2 years ago

csandman commented 2 years ago

This would partially fulfill the requests from #2, however it is missing the original two sites requested, GitLab and Gitea. I was going to do GitLab, but it appears they already offer icons from the material icon pack so I decided to leave that out for now. I also thought it best not to make this PR too large. Someone else could definitely add to this if they wanted to though.

This PR adds support for Azure DevOps and BitBucket by separating all of the site specific code and element selectors into a new object specific to each one. I'm not sure if this new code style is formatted like you'd expect, but I'm willing to change it if need be. There were a lot of changes here, so I wouldn't be surprised if there are things you want changed. I could also split this into two separate PR's for each of the Git providers if you'd like, but keeping it all together makes it a little easier to see why I broke things down like I did. I'll also try and explain my reasoning for this breakdown here, but I also added comments to the code where it was less than obvious why I made certain choices.


The main part of this change was to create an object for each of the pieces of this code that are specific to each git provider's website. These objects look like this:

{
  name: 'github',
  selectors: {
    row: '.js-navigation-container[role=grid] > .js-navigation-item',
    filename: 'div[role="rowheader"] > span',
    icon: '.octicon',
  },
  getIsLightTheme: () =>
    document.querySelector('html').getAttribute('data-color-mode') === 'light',
  getIsDirectory: (svgEl) => svgEl.getAttribute('aria-label') === 'Directory',
  getIsSubmodule: (svgEl) => svgEl.getAttribute('aria-label') === 'Submodule',
  getIsSymlink: (svgEl) => svgEl.getAttribute('aria-label') === 'Symlink Directory',
  replaceIcon: (svgEl, newSVG) => {
    svgEl
      .getAttributeNames()
      .forEach((attr) => newSVG.setAttribute(attr, svgEl.getAttribute(attr)));

    svgEl.parentNode.replaceChild(newSVG, svgEl);
  },
}

This allowed me to keep most of the actual code for selecting the icon in the common loop of the code instead of separating it out, except for the replaceIcon part which is a bit longer. That function needed to be independent as all of the git providers had different structures for the element, and directly running the same original code for each icon left things styled very inconsistently. For example, BitBucket's icon styles were being set using an svg selector, which wouldn't work on the new icon because an img element is used instead.

BitBucket works very similarly to the way GitHub works, but Azure DevOps raised some issues because of the nature of their repository file tree.

First of all, replacing the original icon element with the new icon completely broke the site every time you navigated to a new folder in a repository. So alternatively, I added the icon as a child of the previous icon element and added styling to hide their original icon. There could be a better approach but this seemed like the safest way to handle it.

Second of all, on the first render the elements are all replaced fine, but when you expanded one of the file tree leaves, the observe function wasn't getting properly triggered for the new elements, and it was leaving old icons attached to new rows. It's hard to explain exactly what was happening but it was essentially just broken. Here's an example of what it looked like:

image

So my solution was to add a native MutationObserver to each of the row elements in addition to the basic observe function, but limiting the icon updates to only mutations that were not triggered by the extension itself, otherwise it would end up in an infinite loop of replacing the icons.

I also changed the way light/dark mode is detected, as the user's light/dark mode system preference might be different from their selected preference on each site. For GitHub it was easy enough as they add an attribute to the html which explicitly says which mode is selected. Azure does not have something as straightforward as this so I added a check for the body's font color. This should be enough, considering they don't have a bunch of alternative themes (only light or dark) unless they decide to change the font color in the future.


If you'd like to test this, you can easily find open source projects on BitBucket to look through, like this one: https://bitbucket.org/galad87/subler/src/master/

For Azure however, you'll need to create an account and make your own repository to test with because (as far as I'm aware) there is no public setting for repos there. It is free to get started though.

Here are some screenshots of the end result for each of them:

Bitbucket

image image

Azure DevOps

image image image
csandman commented 2 years ago

Glad you like it! I pushed a new commit with the change requested (however I removed the break statements as they all follow return statements and are unnecessary). Let me know if there is anything else you need changed!

jamiehaywood commented 2 years ago

I'm unfortunately not the/a maintainer but I thought I would give my two cents anyway, as I think this should be merged and pushed

csandman commented 2 years ago

Ah, my bad I totally missed that haha. Well, if @Claudiohbsantos checks it out at some point, it would be great to see this merged!

Claudiohbsantos commented 2 years ago

I'm really sorry! No idea how I've missed this for so long 🤦. I recently moved to Gitlab at work so my GitHub notifications have been sorely neglected.

I'll try to take a look at this and any other pending issues in this repo this weekend

Claudiohbsantos commented 2 years ago

I resolved the merge conflict I just created with my last push

csandman commented 2 years ago

I tackled all of the comments you left on this PR, hopefully everything is up to snuff now! Sorry about that bug, I somehow missed that when making the changes recommended by @jamiehaywood.

csandman commented 2 years ago

Sorry, I accidentally merged my eslint branch into this one, not really sure how that happened. I meant to do it the other way around haha.

csandman commented 2 years ago

I ended up adding one last change to the core functionality of this PR that I hope isn't outside of it's scope. I ended up changing the selectors for the GitHub config to allow for replacement in the new PR file explorer view.

image

I originally tried making a new provider config that matched that URL but I realized it wouldn't work for the normal view if you navigated between pages. So instead I just modified the selectors to allow it to select either the rows in the standard codebase view or the file tree view. I also had to make the icon selector more specific to avoid matching the chevron icons in the file tree view.

Overall, I can't think of any scenario where having these OR css selectors would cause any conflicts.

If this is outside of the scope of this PR and you want me to revert, lmk.

You can see the change here: https://github.com/Claudiohbsantos/github-material-icons-extension/pull/31/commits/972c5e186ca03b0a6ea68175917c43202a65f339