daattali / oldschool-github-extension

Revert GitHub's UI back to its classic look (before the June 23, 2020 update that has a flat, rounded and more whitespaced design).
https://chrome.google.com/webstore/detail/old-school-github/blkkkhifjoiedclojflfcenbjigdajeb
MIT License
229 stars 11 forks source link

Move the "Languages" section up #7

Closed pkkm closed 4 years ago

pkkm commented 4 years ago

Before the redesign, the repo's programming language was at the top, which matched what I first look at when searching for libraries: description, language, number of commits, date of last commit. Now, the language is at the bottom of the sidebar, below the much less useful "Contributors" and "Latest release" sections. Perhaps this extension could rearrange the sections so that "Languages" is second, just below "About"?

daattali commented 4 years ago

I cannot make any major layout changes, only style changes. Moving things to other places is not something I can do with CSS (technically it may be possible, but it would be a mess).

Unfortunately as much as I hate the current sidebar layout, it's extremely difficult to change that with CSS.

daattali commented 4 years ago

I've added a "Limitations" section to the README because a few people asked about this

pkkm commented 4 years ago

Are you opposed to using JS in the extension? If not, this should be pretty easy to do without flexbox tricks. I just hacked together a proof of concept in Greasemonkey and it works in my browser:

// ==UserScript==
// @name     Move Languages section up (for Old School GitHub)
// @include  *://github.com/*
// @run-at   document-end
// @grant    none
// ==/UserScript==

function log(message) {
  console.log('Old School GitHub: Move "Languages" up: ' + message);
}

function isLanguagesSection(sectionDiv) {
  return Array.prototype.some.call(
    sectionDiv.getElementsByTagName("h2"),
    h => h.textContent === "Languages"
  );
}

function main() {
  const sidebar = document.querySelector("div.BorderGrid.BorderGrid--spacious");
  if (sidebar === null) {
    log("Cannot find sidebar, stopping");
    return;
  }

  const sections = sidebar.querySelectorAll("div.BorderGrid-row");
  if (sections.length < 2) {
    log("Sidebar has less than 2 sections, stopping");
    return;
  }

  const languagesSection = Array.prototype.find.call(sections, isLanguagesSection);
  if (languagesSection === undefined) {
    log("Cannot find languages section, stopping");
    return;
  }

  sidebar.insertBefore(languagesSection, sections[1]);
}

main();
daattali commented 4 years ago

I originally was going to tell you why I didn't use JS but I stopped because the reply was getting very long.

I did initially wanted to do some things with JS in this extension to fix the layout. But I soon discovered that github does something very strange: some pages are actual page reloads, but some pages are fully AJAX. If you're on the Code tab and you click on Pull Requests then you don't actually refresh the page, but if you click on Issues then it is a new page. Even though Issues and PR are very similar pages... what that meant is that after moving from Code to Pull Requests, any JS changes were reverted because large portions of the page body were re-written. Technically we can try to find ways around that, using event listeners or mutator observers or any other technique and try to force a re-initialization of the javascript when a new page is AJAX-loaded, but that sounds like it would be buggy and very difficult to make it work correctly. So I had to give up on that and switch to a fully CSS solution unfortunately.

pkkm commented 4 years ago

You're right, I didn't notice the fully AJAX loads before. I've worked around them now by watching the progress bar. It's pretty hacky so I understand if you don't want to use it, but I'll share my code anyway in case someone who's also writing a userscript comes across this issue and finds it helpful.

// ==UserScript==
// @name     Move Languages section up (for Old School GitHub)
// @include  *://github.com/*
// @run-at   document-end
// @grant    none
// ==/UserScript==

function log(message) {
  console.log('Old School GitHub: Move "Languages" up: ' + message);
}

function isLanguagesSection(sectionDiv) {
  return Array.prototype.some.call(
    sectionDiv.getElementsByTagName("h2"),
    h => h.textContent === "Languages"
  );
}

function moveSection() {
  const sidebar = document.querySelector("div.BorderGrid.BorderGrid--spacious");
  if (sidebar === null) {
    log("Cannot find sidebar, stopping");
    return;
  }

  const sections = sidebar.querySelectorAll("div.BorderGrid-row");
  if (sections.length < 2) {
    log("Sidebar has less than 2 sections, stopping");
    return;
  }

  const languagesSection = Array.prototype.find.call(sections, isLanguagesSection);
  if (languagesSection === undefined) {
    log("Cannot find languages section, stopping");
    return;
  }

  sidebar.insertBefore(languagesSection, sections[1]);
}

function main() {
  moveSection();

  // When browsing GitHub, some clicks cause actual page loads while others are
  // fully AJAX. To handle the latter, we watch the progress bar at the top of
  // the page and reapply our changes when it loses the "is-loading" class.

  const progressBar = document.querySelector("span.progress-pjax-loader");
  if (progressBar === null) {
    log("Cannot find progress bar at the top of the page");
    return;
  }

  const observer = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
      if (mutation.type !== "attributes") {
        return;
      }

      if (mutation.target.classList.contains("is-loading")) {
        return;
      }

      log("Detected AJAX page load, reapplying changes");
      moveSection();
    });
  });

  observer.observe(progressBar, { attributes: true, attributeFilter: ["class"] });
}

main();
daattali commented 4 years ago

Thanks for sharing.

I don't want to include something like this in the extension officially for performance reasons (and also because it's very hacky 😛) but it can definitely be useful for someone to use individually