Reputation: 33
I'm working on my first extension - Tea timer. After choosing a tea type/entering number of minutes timer will start running. The problem is that when I change my tab or close the extension, the timer will stop running although I would like it to run in the background. I'm not sure how to handle this with chrome.storage.
Here is my timer.js:
function timer(seconds) {
clearInterval(countdown);
const now = Date.now();
const then = now + seconds * 1000;
displayTimeLeft(seconds);
displayEndTime(then);
countdown = setInterval(() => {
const secondsLeft = Math.round((then - Date.now()) / 1000);
if (secondsLeft < 0) {
clearInterval(countdown);
const soundEffect = new Audio("tibetan.mp3");
soundEffect.play();
setTimeout(function() {
alert("Your tea is ready!");
}, 500);
return;
}
displayTimeLeft(secondsLeft);
}, 1000);
}
function displayTimeLeft(seconds) {
const minutes = Math.floor(seconds / 60);
const remainderSeconds = seconds % 60;
const display = `${minutes}:${
remainderSeconds < 10 ? "0" : ""
}${remainderSeconds}`;
if (timerDisplay) {
timerDisplay.textContent = display;
}
//console.log({ minutes, remainderSeconds });
}
function startTimer() {
const seconds = parseInt(this.dataset.time);
console.log(seconds);
timer(seconds);
}
buttons.forEach(button => button.addEventListener("click", startTimer));
background.js
chrome.runtime.onInstalled.addListener(function() {
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([
{
conditions: [new chrome.declarativeContent.PageStateMatcher({})],
actions: [new chrome.declarativeContent.ShowAction()]
}
]);
});
});
Thank you all in advance!
Upvotes: 1
Views: 6030
Reputation: 772
Move the setInterval() code to background script and change "Persistent" property for background script in manifest to "True"
This allows extension to continue running background script even if the popup window of extension is closed and setInterval() will continue to run.
NOTE: You should be careful when you change "Persistent" property to "True". Make sure chrome webstore allows it without any issues.
Upvotes: 0
Reputation: 22474
Since time.js is part of a pop-up window, the code in that file (as well as the interval you've set using setInterval
) will stop running as soon as the pop-up window is closed.
In order to make this work, you'll have to move the interval to the background page, the background page's context can be set to stay on as long as the browser is opened.
By the way, the code that is currently in background.js doesn't do anything and you only need something like that if you want to use page actions
Here is my approach for doing that:
background.js
let timerID;
let timerTime;
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.cmd === 'START_TIMER') {
timerTime = new Date(request.when);
timerID = setTimeout(() => {
// the time is app, alert the user.
}, timerTime.getTime() - Date.now());
} else if (request.cmd === 'GET_TIME') {
sendResponse({ time: timerTime });
}
});
timer.js
// Call this when the pop-up is shown
chrome.runtime.sendMessage({ cmd: 'GET_TIME' }, response => {
if (response.time) {
const time = new Date(response.time);
startTimer(time)
}
});
functions startTimer(time) {
if (time.getTime() > Date.now()) {
setInterval(() => {
// display the remaining time
}, 1000)
}
}
function startTime(time) {
chrome.runtime.sendMessage({ cmd: 'START_TIMER', when: time });
startTimer(time);
}
Essentially, when the user starts a timer, you send a message to the background script with a future date for when the timer is done. Then, in the background script you set a timeout to be triggered at that date so you can do something (play a sound) even if the pop-up window is closed. Then, when the pop-up window is reopened, you send a message to the background script and it will send back the date for the timer that was previously set.
This can be improved, for now, this will work correctly as long as the browser is opened for the entire length of the timer, to make it work even if the browser is closed and reopened, you can save and restore the timer's date from storage.
Upvotes: 3