Skip to content

Commit 67094b8

Browse files
committed
Add TabTime Guardian browser extension for time management
1 parent ea870dc commit 67094b8

File tree

6 files changed

+332
-0
lines changed

6 files changed

+332
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# TabTime Guardian
2+
3+
A browser extension designed to help users manage their time on any website by setting a session timer. Once the set time expires, the active tab closes automatically, promoting productive and time-conscious browsing.
4+
5+
## Features
6+
7+
- **Custom Timer**: Set a personalized time limit for any website session.
8+
- **Auto Tab Close**: Automatically closes the active tab once the timer runs out.
9+
- **Simple Interface**: User-friendly design for seamless interaction.
10+
11+
## Advantages of TabTime Guardian
12+
13+
- **Enhanced Productivity**: Set time limits for any site (e.g., YouTube, social media) to stay focused without distractions.
14+
- **Time Management**: The auto-closure feature ensures adherence to your planned schedule.
15+
- **User Control**: Full control over how much time to spend on a site, ensuring balanced usage.
16+
- **Lightweight**: Easy to use, integrates seamlessly with your browser without being intrusive.
17+
18+
## How to Use It
19+
20+
1. **Clone the Repository**:
21+
22+
```bash
23+
git clone https://github.com/your-repo-url.git
24+
cd tabtime-guardian
25+
```
26+
27+
2. **Add the Extension to Your Browser**:
28+
29+
* Open your browser’s extension page:
30+
* **For Chrome**: Go to `chrome://extensions/`
31+
* **For Edge**: Go to `edge://extensions/`
32+
* Enable "Developer mode" (located in the top right corner).
33+
* Click on **"Load unpacked"** and select the folder containing the cloned project files.
34+
* The extension will now appear in your browser’s toolbar.
35+
36+
3. **Start Using TabTime Guardian**:
37+
38+
* Open any website (e.g., YouTube, social media, or any platform where you want to manage your time).
39+
* Click the extension icon in your browser toolbar to open the settings popup.
40+
* Use the `+` and `-` buttons to set your desired time limit.
41+
* Click "Start" to initiate the session timer.
42+
* Once the timer ends, the active tab will automatically close, helping you manage your time more effectively.
43+
44+
## Additional Info
45+
46+
Feel free to fork this project or suggest improvements by opening an issue on GitHub. Stay productive with **TabTime Guardian**!
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
chrome.runtime.onInstalled.addListener(() => {
2+
chrome.storage.local.set({
3+
timerEndTime: 0,
4+
timerMinutes: 0,
5+
youtubeTabId: null,
6+
});
7+
});
8+
9+
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
10+
console.log("Message received in background script:", message);
11+
12+
if (message.action === "startTimer") {
13+
chrome.storage.local.get(["timerMinutes"], (data) => {
14+
const timerMilliseconds = data.timerMinutes * 60000;
15+
const endTime = Date.now() + timerMilliseconds;
16+
17+
chrome.storage.local.set({ timerEndTime: endTime }, () => {
18+
chrome.alarms.create("sessionAlarm", { when: endTime });
19+
console.log(
20+
"Timer started for",
21+
data.timerMinutes,
22+
"minutes. Alarm set for",
23+
new Date(endTime).toLocaleTimeString()
24+
);
25+
26+
// Store the current tab ID as the YouTube tab ID
27+
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
28+
if (tabs.length > 0) {
29+
chrome.storage.local.set({ youtubeTabId: tabs[0].id });
30+
console.log("YouTube tab ID stored:", tabs[0].id);
31+
}
32+
});
33+
});
34+
});
35+
} else if (message.action === "getRemainingTime") {
36+
chrome.storage.local.get(["timerEndTime"], (data) => {
37+
const remainingTime = Math.max(0, data.timerEndTime - Date.now());
38+
sendResponse({ remainingTime });
39+
});
40+
return true; // Indicates that the response will be sent asynchronously
41+
}
42+
});
43+
44+
chrome.alarms.onAlarm.addListener((alarm) => {
45+
if (alarm.name === "sessionAlarm") {
46+
chrome.storage.local.get(["youtubeTabId"], (data) => {
47+
console.log("Attempting to close tab with ID:", data.youtubeTabId);
48+
if (data.youtubeTabId) {
49+
chrome.tabs.remove(data.youtubeTabId, () => {
50+
console.log("Tab closed");
51+
// Reset the youtubeTabId to null
52+
chrome.storage.local.set({ youtubeTabId: null });
53+
});
54+
} else {
55+
console.log("No YouTube tab ID found");
56+
}
57+
});
58+
}
59+
});
60+
61+
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
62+
if (message.action === "resetTimer") {
63+
chrome.alarms.clear("sessionAlarm"); // Clear the current timer
64+
chrome.storage.local.set({
65+
timerEndTime: 0,
66+
youtubeTabId: null,
67+
});
68+
console.log("Timer reset.");
69+
}
70+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"manifest_version": 3,
3+
"name": "YouTube Session Manager",
4+
"version": "1.0",
5+
"description": "Set a timer for your YouTube session and automatically close the tab when the timer ends.",
6+
"permissions": ["tabs", "storage", "activeTab", "alarms"],
7+
"background": {
8+
"service_worker": "background.js"
9+
},
10+
"action": {
11+
"default_popup": "popup.html"
12+
},
13+
"host_permissions": ["https://*.youtube.com/*"]
14+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>YouTube Session Manager</title>
5+
<link rel="stylesheet" href="styles.css" />
6+
</head>
7+
<body>
8+
<div class="container">
9+
<h1>TabTime Guardian</h1>
10+
<div class="timer-container">
11+
<label for="time" class="timer-label">Set Timer:</label>
12+
<div id="time-display" class="time-display">0:00</div>
13+
<div class="button-group">
14+
<button id="decrease" class="button">-</button>
15+
<button id="increase" class="button">+</button>
16+
</div>
17+
<button id="start" class="start-button">Start</button>
18+
<button id="reset" class="reset-button">Reset</button>
19+
</div>
20+
</div>
21+
<script src="popup.js"></script>
22+
</body>
23+
</html>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
let totalMinutes = 0;
2+
let countdownInterval;
3+
4+
function updateTimeDisplay(minutes, seconds) {
5+
const hours = Math.floor(minutes / 60);
6+
const displayMinutes = minutes % 60;
7+
const timeDisplay = document.getElementById("time-display");
8+
timeDisplay.textContent = `${hours}:${displayMinutes < 10 ? "0" : ""}${displayMinutes}:${seconds < 10 ? "0" : ""}${seconds}`;
9+
console.log(`Time Display Updated: ${hours}h ${displayMinutes}m ${seconds}s`);
10+
}
11+
12+
function startCountdown(totalSeconds) {
13+
clearInterval(countdownInterval); // Clear any existing interval
14+
countdownInterval = setInterval(() => {
15+
if (totalSeconds <= 0) {
16+
clearInterval(countdownInterval); // Stop countdown when time reaches 0
17+
enableButtons(); // Re-enable buttons when the timer ends
18+
return;
19+
}
20+
totalSeconds--;
21+
const minutes = Math.floor(totalSeconds / 60);
22+
const seconds = totalSeconds % 60;
23+
updateTimeDisplay(minutes, seconds);
24+
}, 1000);
25+
}
26+
27+
function disableButtons() {
28+
document.getElementById("increase").disabled = true;
29+
document.getElementById("decrease").disabled = true;
30+
document.getElementById("reset").disabled = false; // Enable reset when the timer starts
31+
}
32+
33+
function enableButtons() {
34+
document.getElementById("increase").disabled = false;
35+
document.getElementById("decrease").disabled = false;
36+
document.getElementById("reset").disabled = true; // Disable reset when there's no timer running
37+
}
38+
39+
document.getElementById("increase").addEventListener("click", () => {
40+
totalMinutes++;
41+
updateTimeDisplay(totalMinutes, 0);
42+
});
43+
44+
document.getElementById("decrease").addEventListener("click", () => {
45+
if (totalMinutes > 0) {
46+
totalMinutes--;
47+
updateTimeDisplay(totalMinutes, 0);
48+
}
49+
});
50+
51+
document.getElementById("start").addEventListener("click", () => {
52+
console.log("Start button clicked");
53+
if (totalMinutes <= 0) {
54+
alert("Please set a valid timer.");
55+
return;
56+
}
57+
58+
// Save the timer minutes in storage and start the countdown
59+
chrome.storage.local.set({ timerMinutes: totalMinutes }, () => {
60+
const totalSeconds = totalMinutes * 60;
61+
startCountdown(totalSeconds);
62+
chrome.runtime.sendMessage({ action: "startTimer" });
63+
disableButtons(); // Disable + and - buttons when the timer starts
64+
});
65+
});
66+
67+
// Reset button functionality
68+
document.getElementById("reset").addEventListener("click", () => {
69+
console.log("Reset button clicked");
70+
71+
// Clear the countdown
72+
clearInterval(countdownInterval);
73+
74+
// Reset the timer to 0
75+
totalMinutes = 0;
76+
updateTimeDisplay(totalMinutes, 0);
77+
78+
// Notify the background script to reset the timer
79+
chrome.runtime.sendMessage({ action: "resetTimer" });
80+
81+
// Re-enable + and - buttons
82+
enableButtons();
83+
});
84+
85+
// Initialize display with time from storage if available
86+
chrome.runtime.sendMessage({ action: "getRemainingTime" }, (response) => {
87+
if (response && response.remainingTime) {
88+
const totalSeconds = Math.floor(response.remainingTime / 1000);
89+
startCountdown(totalSeconds);
90+
disableButtons(); // Keep buttons disabled if there's already an active timer
91+
} else {
92+
updateTimeDisplay(totalMinutes, 0);
93+
enableButtons(); // Enable buttons if there's no active timer
94+
}
95+
});
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
body {
2+
font-family: Arial, sans-serif;
3+
background-color: #f4f4f4;
4+
margin: 0;
5+
padding: 0;
6+
display: flex;
7+
justify-content: center;
8+
align-items: center;
9+
height: 100vh;
10+
}
11+
12+
.container {
13+
background-color: #fff;
14+
padding: 20px;
15+
border-radius: 10px;
16+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
17+
text-align: center;
18+
width: 300px;
19+
}
20+
21+
h1 {
22+
margin-top: 0;
23+
color: #333;
24+
}
25+
26+
.timer-container {
27+
margin-top: 20px;
28+
}
29+
30+
.timer-label {
31+
font-size: 1.2em;
32+
color: #555;
33+
}
34+
35+
.time-display {
36+
font-size: 2em;
37+
margin: 10px 0;
38+
color: #0073e6;
39+
font-weight: bold;
40+
}
41+
42+
.button-group {
43+
display: flex;
44+
justify-content: center;
45+
gap: 10px;
46+
margin-bottom: 20px;
47+
}
48+
49+
.button {
50+
background-color: #0073e6;
51+
color: #fff;
52+
border: none;
53+
padding: 10px 20px;
54+
font-size: 1.2em;
55+
border-radius: 5px;
56+
cursor: pointer;
57+
transition: background-color 0.3s;
58+
}
59+
60+
.button:disabled {
61+
cursor: not-allowed;
62+
opacity: 0.5;
63+
}
64+
65+
.button:hover {
66+
background-color: #005bb5;
67+
}
68+
69+
.start-button,
70+
.reset-button {
71+
background-color: #28a745;
72+
color: #fff;
73+
border: none;
74+
padding: 10px 20px;
75+
font-size: 1.2em;
76+
border-radius: 5px;
77+
cursor: pointer;
78+
transition: background-color 0.3s;
79+
}
80+
81+
.start-button:hover,
82+
.reset-button:hover {
83+
background-color: #218838;
84+
}

0 commit comments

Comments
 (0)