Tried to rough chome extension to show number like/dislike for seen LeetCode problems on problem list page

I solve LeetCode problems sometimes per week.

Basically I choose Easy or Medium.

There are some problems which number of dislike is much higher than number of like. Such problems are sometimes too difficult or have strange edge case I think. I just skip such problems.

But, I easy to forget previously checked such problems and I need to access each problem page to see number of like/dislike.

It’s waste of time, so I tried to develop a tiny chrome extension to show number of like/dislike for checked problems on problem list page. After enabling the chrome extension, problem list page will be like follwoings.

The extension uses LocalStorage, so it can’t show number of like/dislike after clearing LocalStorage、it just shows number of like/dislike for only checked problems. But, the extension is just for me and I don’t publish it to the store, so it should be Okay.

Repository and how to use

I pushed the code to the following Github repository.

Google Chrome extension to save number of like and dislike at last visit time for each problems and show them on problem list page. - zuqqhi2/leetcode-show-numlike
zuqqhi2/leetcode-show-numlike - GitHub

How to install is opening to Google Chrome extension setting page and selecting “leetcode-show-numlike” directory after clicking extension loading without package button. (The following image is Japanese version)

After that, you can see “like,dislike” column on LeetCode problem list page. “0, 0” for unseen problems.

The extension is just adding “like,dislike” column right after opening page, so the column will be disappeared after moving page using pagination. So, it better to set “rows per page” to “all”.

How to develop Chrome extension

This is my first chrome exntension, but it was very easy.

Minimum requirements are putting manifest.json and main Javascript file to same directory like following.

$ tree zuqqhi2-ext-test/
zuqqhi2-ext-test/
├── app.js
└── manifest.json
 
0 directories, 2 files 

You can see dialog box on LeetCode problem list page like the following screenshot after install chrome exntesion with the following manifest.json and app.js.

 {
  "name": "Zuqqhi2ExtTest",
  "version": "0.1.0",
  "manifest_version": 2,
  "description": "Test.",
  "content_scripts": [{
    "matches": ["https://leetcode.com/problemset/all/*"],
    "js": ["app.js"],
    "css": []
   }],
   "permissions": []
 } 
alert('Test'); 

Above sample and the extension which I develop don’t set any permission, but I learned permission setting from the following website.

Use the permissions key to request special powers for your extension. This key is an array of strings, and each string is a request for a permission.
permissions - Mozilla | MDN - 

Code

The extension just does the followings.

  1. Waiting for loading elements which it uses.
  2. On problem list page, it append a column to the table and add number of like/dislike loaded from LocalStorage.
  3. On each problem page, it save number of like/dislike to LocalStorage.

loadProblemInfo function just load number of like/dislike from LocalStorage.

// Common functions
function loadProblemInfo() {
  // Clean or initialize localStorage
  var problem_info = {}
  if (localStorage.getItem('zuqqhi2-leetcode-show-numlike')) {
    try {
      problem_info = JSON.parse(localStorage.getItem('zuqqhi2-leetcode-show-numlike'))
    } catch (e) {
      localStorage.removeItem('zuqqhi2-leetcode-show-numlike')
      localStorage.setItem('zuqqhi2-leetcode-show-numlike', '{}')
    }
  } else {
    localStorage.setItem('zuqqhi2-leetcode-show-numlike', '{}')
  }

  return problem_info
}

The extension waits for loading elements which it uses because it doesn’t work without waiting.

For waiting elements, I use MutationObserver for problem list page, but I use setInterval instead of MutationObserver on each problem page because MutationObserver didn’t work. On each problem page, it checks elements every 500 msec, it save number of like/dislike when loading elements is finished.

It uses “btn__r7r7” class to get number of like/dislike on each problem page (I couldn’t find another way), so maybe it won’t work after LeetCode each problem page change even if small change.
// Problem list page (Show number of like and dislike)
var observer = undefined
if (document.location.href.startsWith('https://leetcode.com/problemset/all/')) {
  observer = new MutationObserver(() => {
    const elems = document.querySelectorAll(".question-list-base > .question-list-table > .table > .reactable-data > tr")
    if (elems.length > 0) {
      ...
      observer.disconnect()
    }
  })

  const targetNode = document.getElementsByClassName('question-list-base')[0]
  observer.observe(
    targetNode,
    {childList: true, subtree: true}
  )
 
// Each problem page (Save number of like and dislike)
// Note: MutationOberser doesn't work on this page. So, just using setInterval function.
} else {
  observer = () => {
    const elems = document.querySelectorAll(".btn__r7r7")
    if (elems.length === 4) {
      ...
    }
  }

  const observation = () => {
    console.log('zuqqhi2-leetcode-show-numlike: under observation...')
    const targetNode = document.getElementsByClassName('btn__r7r7')[0]
    if (targetNode !== undefined) {
      console.log('zuqqhi2-leetcode-show-numlike: observation is finished')
      observer()
      return true
    } else {
      return false
    }
  }
  const interval_id = setInterval(() => {
    if (observation()) { clearInterval(interval_id); }
  }, 500)
}
zuqqhi2