Super Anki

Supercharges AnkiWeb. Currently Supported Functionality - Show card total, done and remaining count per session - Dark Mode

目前為 2025-01-19 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Super Anki
// @version      5
// @grant        none
// @match        https://*.ankiuser.net/**
// @match        https://*.ankiweb.net/decks
// @description  Supercharges AnkiWeb. Currently Supported Functionality - Show card total, done and remaining count per session - Dark Mode
// @namespace    asleepysamurai.com
// @license      BSD Zero Clause License
// ==/UserScript==

function getTodaysDoneCount(done){
  const now = new Date()
  const cutOffTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 4, 0, 0)
  if(now.getHours() < 4){
    cutOffTime.setTime(cutOffTime.getTime() - (1000 * 60 * 60 * 24))
  }
  
  const key = 'super-anki-data'
  const savedData = JSON.parse(localStorage.getItem(key)) || {}
  if(done === 0 && savedData.doneCount !== undefined && savedData.lastSavedTime && savedData.lastSavedTime >= cutOffTime.getTime()){
    done = savedData.doneCount
  }
  
  localStorage.setItem(key, JSON.stringify({doneCount: done, lastSavedTime: now.getTime()}))
  return done
}

function formatCounts(total, remaining){
  const done = getTodaysDoneCount(total - remaining)
  return `${remaining} Left + ${done} Done = ${total}`
}

function addTotalCount(){
  const counts = Array.from(document.querySelectorAll('.count'))
  
  const equals = document.createTextNode(' = ')
  
  const totalCards = counts.reduce((total, thisCount) => total + parseInt(thisCount.innerText), 0)
  const totalCount = counts[0].cloneNode(true)
  totalCount.innerText = formatCounts(totalCards, totalCards)
  totalCount.classList.remove('active', 'new', 'learn', 'review')
  
  const countParent = counts[0].parentElement
  countParent.appendChild(equals)
  countParent.appendChild(totalCount)
  
  const observer = new MutationObserver(() => {
    debugger
    const restCards = counts.reduce((total, thisCount) => total + parseInt(thisCount.innerText), 0)
    totalCount.innerText = formatCounts(totalCards, restCards)
  })

  counts.forEach(countNode => observer.observe(countNode, { characterData: true, attributes: false, childList: true, subtree: true }));
}

function setupObserver(){
  try{
    init()
  }catch(err){
    setTimeout(() => {
    	setupObserver()
    }, 100)
  }
}

function enableDarkMode(){
  const style = document.documentElement.getAttribute('style')
  document.documentElement.setAttribute('style', `${style || ''}; filter: invert(0.9);`)
}

function updateBranding(){
  document.querySelector('.navbar-brand > span').innerHTML = 'SuperAnki <small><small>v5</small></small>'
}

function init(){
  updateBranding()
  enableDarkMode()
  
  if(window.location.pathname.toLowerCase().startsWith('/study')){
    addTotalCount()
  }
}

setupObserver()