Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: fix timer inconsistencies #20

Open
marwanhawari opened this issue Apr 16, 2023 · 2 comments
Open

bug: fix timer inconsistencies #20

marwanhawari opened this issue Apr 16, 2023 · 2 comments
Labels
bug Something isn't working extension A label for the LeetRooms web extension code

Comments

@marwanhawari
Copy link
Owner

marwanhawari commented Apr 16, 2023

There are currently 2 issues with the timer:

  1. Timer drift causes everybody's timer to be out of sync.

  2. The timer will pause if you go to a different tab for too long. When you come back it will resume, but the time will be completely wrong. Only after you refresh the page will the timer display the proper time remaining.

These fixes should be implemented purely in the React app. I don't expect any chrome extension or server changes to be necessary.

@marwanhawari marwanhawari changed the title bug: fixer timer inconsistencies bug: fix timer inconsistencies Apr 16, 2023
@marwanhawari marwanhawari added bug Something isn't working extension A label for the LeetRooms web extension code labels Apr 16, 2023
@marwanhawari
Copy link
Owner Author

#24 fixes point number 2 above

@mattcarlotta
Copy link

mattcarlotta commented May 7, 2023

@marwanhawari Here's a solution that should fix the timer bug inconsistencies. I can submit a PR, but before I do, I'd recommend that you validate this code locally within the extension. Unfortunately, I don't use Chrome, so I don't have any way to validate myself.

In summary, regardless of when the tab becomes active, the state will become in sync because it recalculates the time left by using the end date minus the current date instead of the previous date in state.

Bugfix code
import { useState, useEffect, useRef } from "react";
import StopwatchIcon from "../icons/StopwatchIcon";

function calculateTimeLeft(eT: Date) {
  const tL = eT.getTime() - new Date().getTime();
  const exp = tL <= 0;

  let h = Math.floor((tL % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  let m = Math.floor((tL % (1000 * 60 * 60)) / (1000 * 60));
  let s = Math.floor((tL % (1000 * 60)) / 1000);

  if (exp) {
    h = 0;
    m = 0;
    s = 0;
  }

  return {
    expired: exp,
    hours: h.toString().padStart(2, "0"),
    minutes: m.toString().padStart(2, "0"),
    seconds: s.toString().padStart(2, "0")
  };
}

type TimeLeft = {
  expired: boolean;
  hours: string;
  minutes: string;
  seconds: string;
};

/*
  When endTime is created, it should be static and the same for all users

  const endTime = new Date();
  endTime.setHours(endTime.getHours() + 1);
*/

export default function Timer({ endTime }: { endTime: Date }) {
  const [timeLeft, setTimeLeft] = useState<TimeLeft>(calculateTimeLeft(endTime));
  const timer = useRef<NodeJS.Timer | null>(null);

  useEffect(() => {
    function updateTime() {
      const newTime = calculateTimeLeft(endTime);

      if (newTime.expired && timer.current) {
        clearInterval(timer.current);
        timer.current = null;
      }

      setTimeLeft(newTime);
    }

    timer.current = setInterval(updateTime, 1000);

    return () => {
      if (timer.current) clearInterval(timer.current);
    };
  }, [endTime]);

  return (
    <div
      className="mt-2 flex flex-col items-center justify-center rounded-md px-2 py-[8px] text-xs transition-all dark:bg-lc-fg ${
        expired ? "text-lc-hd-fg-light dark:text-lc-hd-fg" : ""
      }`}
    >
      <div className="flex items-center gap-2">
        <StopwatchIcon />
        <time className="font-mono">{timeLeft.hours}:{timeLeft.minutes}:{timeLeft.seconds}</time>
      </div>
    </div>
  );
}

Working Demo

or you can edit the demo's code by clicking the button below:

Edit Bug Fix - Leet Code Rooms Issue #20

📝 Just note that this solution still relies upon the client machine to have their time in-sync with actual time. Otherwise, users will still see a different countdown timer. An alternative solution for this would be to generate and recalculate the time left on a server via a websocket. The main draw back with this would be that you'll incur more bandwidth usage.

On an unrelated note, ideally you'll want to use semantic HTML for text -- like utilizing a time or p element. Otherwise, TTS readers won't be able to read the text within a div element. If you're not interested in making the extension web-accessible, then please disregard this note.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working extension A label for the LeetRooms web extension code
Projects
None yet
Development

No branches or pull requests

2 participants