prime8dev

prime8dev
git clone https://git.prime8.dev/prime8dev.git
Log | Files | Refs | README | LICENSE

wakatime.js (2378B)


      1 const WAKATIME_TTL_MS = 60 * 60 * 1000;
      2 
      3 const wakatimeCache = {
      4   data: null,
      5   timestamp: 0,
      6   pending: null,
      7 };
      8 const wakatimeListeners = new Set();
      9 let wakatimeRefreshTimer = 0;
     10 let wakatimeRefreshing = null;
     11 
     12 export async function getWakaTimeData(force = false) {
     13   if (!force && wakatimeCache.data && isFresh(wakatimeCache.timestamp)) {
     14     return wakatimeCache.data;
     15   }
     16 
     17   if (wakatimeCache.pending) {
     18     return wakatimeCache.pending;
     19   }
     20 
     21   wakatimeCache.pending = fetch("/api/wakatime", { credentials: "same-origin" })
     22     .then((res) => (res.ok ? res.json() : null))
     23     .then((data) => {
     24       if (data) {
     25         wakatimeCache.data = data;
     26         wakatimeCache.timestamp = Date.now();
     27       }
     28       // a failed or empty fetch (offline right after wake, a 5xx) keeps the
     29       // last good value instead of wiping it
     30       return data || wakatimeCache.data;
     31     })
     32     .catch(() => wakatimeCache.data)
     33     .finally(() => {
     34       wakatimeCache.pending = null;
     35     });
     36 
     37   return wakatimeCache.pending;
     38 }
     39 
     40 export function subscribeWakaTimeRefresh(listener) {
     41   if (typeof listener !== "function") {
     42     return () => {};
     43   }
     44 
     45   wakatimeListeners.add(listener);
     46   return () => {
     47     wakatimeListeners.delete(listener);
     48   };
     49 }
     50 
     51 export function startWakaTimeRefreshTimer() {
     52   if (wakatimeRefreshTimer) return;
     53 
     54   wakatimeRefreshTimer = window.setInterval(() => {
     55     void refreshWakaTimeData();
     56   }, WAKATIME_TTL_MS);
     57 
     58   // timers are throttled or frozen while the tab is hidden or the laptop
     59   // sleeps; catch up as soon as it is visible and online again
     60   const catchUp = () => {
     61     if (document.visibilityState !== "visible") return;
     62     if (isFresh(wakatimeCache.timestamp)) return;
     63     void refreshWakaTimeData();
     64   };
     65   document.addEventListener("visibilitychange", catchUp);
     66   window.addEventListener("online", catchUp);
     67   window.addEventListener("focus", catchUp);
     68 }
     69 
     70 function isFresh(timestamp) {
     71   return Date.now() - timestamp < WAKATIME_TTL_MS;
     72 }
     73 
     74 async function refreshWakaTimeData() {
     75   if (wakatimeRefreshing) {
     76     return wakatimeRefreshing;
     77   }
     78 
     79   wakatimeRefreshing = getWakaTimeData(true)
     80     .then((data) => {
     81       for (const listener of wakatimeListeners) {
     82         try {
     83           listener(data);
     84         } catch {}
     85       }
     86 
     87       return data;
     88     })
     89     .finally(() => {
     90       wakatimeRefreshing = null;
     91     });
     92 
     93   return wakatimeRefreshing;
     94 }