-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add TabTime Guardian browser extension for time management
- Loading branch information
1 parent
ea870dc
commit 67094b8
Showing
6 changed files
with
332 additions
and
0 deletions.
There are no files selected for viewing
46 changes: 46 additions & 0 deletions
46
Vanilla-JS-Projects/Intermediate/TabTime Guardian/Readme.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# TabTime Guardian | ||
|
||
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. | ||
|
||
## Features | ||
|
||
- **Custom Timer**: Set a personalized time limit for any website session. | ||
- **Auto Tab Close**: Automatically closes the active tab once the timer runs out. | ||
- **Simple Interface**: User-friendly design for seamless interaction. | ||
|
||
## Advantages of TabTime Guardian | ||
|
||
- **Enhanced Productivity**: Set time limits for any site (e.g., YouTube, social media) to stay focused without distractions. | ||
- **Time Management**: The auto-closure feature ensures adherence to your planned schedule. | ||
- **User Control**: Full control over how much time to spend on a site, ensuring balanced usage. | ||
- **Lightweight**: Easy to use, integrates seamlessly with your browser without being intrusive. | ||
|
||
## How to Use It | ||
|
||
1. **Clone the Repository**: | ||
|
||
```bash | ||
git clone https://github.com/your-repo-url.git | ||
cd tabtime-guardian | ||
``` | ||
|
||
2. **Add the Extension to Your Browser**: | ||
|
||
* Open your browser’s extension page: | ||
* **For Chrome**: Go to `chrome://extensions/` | ||
* **For Edge**: Go to `edge://extensions/` | ||
* Enable "Developer mode" (located in the top right corner). | ||
* Click on **"Load unpacked"** and select the folder containing the cloned project files. | ||
* The extension will now appear in your browser’s toolbar. | ||
|
||
3. **Start Using TabTime Guardian**: | ||
|
||
* Open any website (e.g., YouTube, social media, or any platform where you want to manage your time). | ||
* Click the extension icon in your browser toolbar to open the settings popup. | ||
* Use the `+` and `-` buttons to set your desired time limit. | ||
* Click "Start" to initiate the session timer. | ||
* Once the timer ends, the active tab will automatically close, helping you manage your time more effectively. | ||
|
||
## Additional Info | ||
|
||
Feel free to fork this project or suggest improvements by opening an issue on GitHub. Stay productive with **TabTime Guardian**! |
70 changes: 70 additions & 0 deletions
70
Vanilla-JS-Projects/Intermediate/TabTime Guardian/background.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
chrome.runtime.onInstalled.addListener(() => { | ||
chrome.storage.local.set({ | ||
timerEndTime: 0, | ||
timerMinutes: 0, | ||
youtubeTabId: null, | ||
}); | ||
}); | ||
|
||
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { | ||
console.log("Message received in background script:", message); | ||
|
||
if (message.action === "startTimer") { | ||
chrome.storage.local.get(["timerMinutes"], (data) => { | ||
const timerMilliseconds = data.timerMinutes * 60000; | ||
const endTime = Date.now() + timerMilliseconds; | ||
|
||
chrome.storage.local.set({ timerEndTime: endTime }, () => { | ||
chrome.alarms.create("sessionAlarm", { when: endTime }); | ||
console.log( | ||
"Timer started for", | ||
data.timerMinutes, | ||
"minutes. Alarm set for", | ||
new Date(endTime).toLocaleTimeString() | ||
); | ||
|
||
// Store the current tab ID as the YouTube tab ID | ||
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { | ||
if (tabs.length > 0) { | ||
chrome.storage.local.set({ youtubeTabId: tabs[0].id }); | ||
console.log("YouTube tab ID stored:", tabs[0].id); | ||
} | ||
}); | ||
}); | ||
}); | ||
} else if (message.action === "getRemainingTime") { | ||
chrome.storage.local.get(["timerEndTime"], (data) => { | ||
const remainingTime = Math.max(0, data.timerEndTime - Date.now()); | ||
sendResponse({ remainingTime }); | ||
}); | ||
return true; // Indicates that the response will be sent asynchronously | ||
} | ||
}); | ||
|
||
chrome.alarms.onAlarm.addListener((alarm) => { | ||
if (alarm.name === "sessionAlarm") { | ||
chrome.storage.local.get(["youtubeTabId"], (data) => { | ||
console.log("Attempting to close tab with ID:", data.youtubeTabId); | ||
if (data.youtubeTabId) { | ||
chrome.tabs.remove(data.youtubeTabId, () => { | ||
console.log("Tab closed"); | ||
// Reset the youtubeTabId to null | ||
chrome.storage.local.set({ youtubeTabId: null }); | ||
}); | ||
} else { | ||
console.log("No YouTube tab ID found"); | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { | ||
if (message.action === "resetTimer") { | ||
chrome.alarms.clear("sessionAlarm"); // Clear the current timer | ||
chrome.storage.local.set({ | ||
timerEndTime: 0, | ||
youtubeTabId: null, | ||
}); | ||
console.log("Timer reset."); | ||
} | ||
}); |
14 changes: 14 additions & 0 deletions
14
Vanilla-JS-Projects/Intermediate/TabTime Guardian/manifest.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"manifest_version": 3, | ||
"name": "YouTube Session Manager", | ||
"version": "1.0", | ||
"description": "Set a timer for your YouTube session and automatically close the tab when the timer ends.", | ||
"permissions": ["tabs", "storage", "activeTab", "alarms"], | ||
"background": { | ||
"service_worker": "background.js" | ||
}, | ||
"action": { | ||
"default_popup": "popup.html" | ||
}, | ||
"host_permissions": ["https://*.youtube.com/*"] | ||
} |
23 changes: 23 additions & 0 deletions
23
Vanilla-JS-Projects/Intermediate/TabTime Guardian/popup.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>YouTube Session Manager</title> | ||
<link rel="stylesheet" href="styles.css" /> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<h1>TabTime Guardian</h1> | ||
<div class="timer-container"> | ||
<label for="time" class="timer-label">Set Timer:</label> | ||
<div id="time-display" class="time-display">0:00</div> | ||
<div class="button-group"> | ||
<button id="decrease" class="button">-</button> | ||
<button id="increase" class="button">+</button> | ||
</div> | ||
<button id="start" class="start-button">Start</button> | ||
<button id="reset" class="reset-button">Reset</button> | ||
</div> | ||
</div> | ||
<script src="popup.js"></script> | ||
</body> | ||
</html> |
95 changes: 95 additions & 0 deletions
95
Vanilla-JS-Projects/Intermediate/TabTime Guardian/popup.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
let totalMinutes = 0; | ||
let countdownInterval; | ||
|
||
function updateTimeDisplay(minutes, seconds) { | ||
const hours = Math.floor(minutes / 60); | ||
const displayMinutes = minutes % 60; | ||
const timeDisplay = document.getElementById("time-display"); | ||
timeDisplay.textContent = `${hours}:${displayMinutes < 10 ? "0" : ""}${displayMinutes}:${seconds < 10 ? "0" : ""}${seconds}`; | ||
console.log(`Time Display Updated: ${hours}h ${displayMinutes}m ${seconds}s`); | ||
} | ||
|
||
function startCountdown(totalSeconds) { | ||
clearInterval(countdownInterval); // Clear any existing interval | ||
countdownInterval = setInterval(() => { | ||
if (totalSeconds <= 0) { | ||
clearInterval(countdownInterval); // Stop countdown when time reaches 0 | ||
enableButtons(); // Re-enable buttons when the timer ends | ||
return; | ||
} | ||
totalSeconds--; | ||
const minutes = Math.floor(totalSeconds / 60); | ||
const seconds = totalSeconds % 60; | ||
updateTimeDisplay(minutes, seconds); | ||
}, 1000); | ||
} | ||
|
||
function disableButtons() { | ||
document.getElementById("increase").disabled = true; | ||
document.getElementById("decrease").disabled = true; | ||
document.getElementById("reset").disabled = false; // Enable reset when the timer starts | ||
} | ||
|
||
function enableButtons() { | ||
document.getElementById("increase").disabled = false; | ||
document.getElementById("decrease").disabled = false; | ||
document.getElementById("reset").disabled = true; // Disable reset when there's no timer running | ||
} | ||
|
||
document.getElementById("increase").addEventListener("click", () => { | ||
totalMinutes++; | ||
updateTimeDisplay(totalMinutes, 0); | ||
}); | ||
|
||
document.getElementById("decrease").addEventListener("click", () => { | ||
if (totalMinutes > 0) { | ||
totalMinutes--; | ||
updateTimeDisplay(totalMinutes, 0); | ||
} | ||
}); | ||
|
||
document.getElementById("start").addEventListener("click", () => { | ||
console.log("Start button clicked"); | ||
if (totalMinutes <= 0) { | ||
alert("Please set a valid timer."); | ||
return; | ||
} | ||
|
||
// Save the timer minutes in storage and start the countdown | ||
chrome.storage.local.set({ timerMinutes: totalMinutes }, () => { | ||
const totalSeconds = totalMinutes * 60; | ||
startCountdown(totalSeconds); | ||
chrome.runtime.sendMessage({ action: "startTimer" }); | ||
disableButtons(); // Disable + and - buttons when the timer starts | ||
}); | ||
}); | ||
|
||
// Reset button functionality | ||
document.getElementById("reset").addEventListener("click", () => { | ||
console.log("Reset button clicked"); | ||
|
||
// Clear the countdown | ||
clearInterval(countdownInterval); | ||
|
||
// Reset the timer to 0 | ||
totalMinutes = 0; | ||
updateTimeDisplay(totalMinutes, 0); | ||
|
||
// Notify the background script to reset the timer | ||
chrome.runtime.sendMessage({ action: "resetTimer" }); | ||
|
||
// Re-enable + and - buttons | ||
enableButtons(); | ||
}); | ||
|
||
// Initialize display with time from storage if available | ||
chrome.runtime.sendMessage({ action: "getRemainingTime" }, (response) => { | ||
if (response && response.remainingTime) { | ||
const totalSeconds = Math.floor(response.remainingTime / 1000); | ||
startCountdown(totalSeconds); | ||
disableButtons(); // Keep buttons disabled if there's already an active timer | ||
} else { | ||
updateTimeDisplay(totalMinutes, 0); | ||
enableButtons(); // Enable buttons if there's no active timer | ||
} | ||
}); |
84 changes: 84 additions & 0 deletions
84
Vanilla-JS-Projects/Intermediate/TabTime Guardian/styles.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
body { | ||
font-family: Arial, sans-serif; | ||
background-color: #f4f4f4; | ||
margin: 0; | ||
padding: 0; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
height: 100vh; | ||
} | ||
|
||
.container { | ||
background-color: #fff; | ||
padding: 20px; | ||
border-radius: 10px; | ||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | ||
text-align: center; | ||
width: 300px; | ||
} | ||
|
||
h1 { | ||
margin-top: 0; | ||
color: #333; | ||
} | ||
|
||
.timer-container { | ||
margin-top: 20px; | ||
} | ||
|
||
.timer-label { | ||
font-size: 1.2em; | ||
color: #555; | ||
} | ||
|
||
.time-display { | ||
font-size: 2em; | ||
margin: 10px 0; | ||
color: #0073e6; | ||
font-weight: bold; | ||
} | ||
|
||
.button-group { | ||
display: flex; | ||
justify-content: center; | ||
gap: 10px; | ||
margin-bottom: 20px; | ||
} | ||
|
||
.button { | ||
background-color: #0073e6; | ||
color: #fff; | ||
border: none; | ||
padding: 10px 20px; | ||
font-size: 1.2em; | ||
border-radius: 5px; | ||
cursor: pointer; | ||
transition: background-color 0.3s; | ||
} | ||
|
||
.button:disabled { | ||
cursor: not-allowed; | ||
opacity: 0.5; | ||
} | ||
|
||
.button:hover { | ||
background-color: #005bb5; | ||
} | ||
|
||
.start-button, | ||
.reset-button { | ||
background-color: #28a745; | ||
color: #fff; | ||
border: none; | ||
padding: 10px 20px; | ||
font-size: 1.2em; | ||
border-radius: 5px; | ||
cursor: pointer; | ||
transition: background-color 0.3s; | ||
} | ||
|
||
.start-button:hover, | ||
.reset-button:hover { | ||
background-color: #218838; | ||
} |