-
Notifications
You must be signed in to change notification settings - Fork 21
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
Comments
#24 fixes point number 2 above |
@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 codeimport { 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>
);
} or you can edit the demo's code by clicking the button below: 📝 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 |
There are currently 2 issues with the timer:
Timer drift causes everybody's timer to be out of sync.
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.
The text was updated successfully, but these errors were encountered: