Skip to content

Commit

Permalink
Merge pull request #9 from ContriHUB/main
Browse files Browse the repository at this point in the history
Contributions from hacktoberfest (contrihub)
  • Loading branch information
Nandika-A authored Oct 10, 2024
2 parents e804090 + e8cbb46 commit a68c9dd
Show file tree
Hide file tree
Showing 17 changed files with 8,287 additions and 139 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
**/.DS_Store
47 changes: 37 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,41 @@
The Eye Protection Google extension is designed to remind users to follow the 20-20-20 rule while using their computers. It integrates seamlessly into the browsing experience, periodically prompting users to take short breaks to reduce eye strain and prevent discomfort associated with prolonged screen exposure.
# Eye Protection Google Extension

# Tech Stack:
HTML, CSS, Javascript
The Eye Protection Google extension is designed to remind users to follow the **20-20-20 rule** while using their computers. It integrates seamlessly into the browsing experience, periodically prompting users to take short breaks to reduce eye strain and prevent discomfort associated with prolonged screen exposure.

# Features:
1. Two timers, for 20 minutes and 20 seconds each
2. Play, pause, restart, and resume the timer
3. Notifications to take breaks and to start the work
## Tech Stack
- **HTML**
- **CSS**
- **JavaScript**

# How to use it:
## Features
- Two timers: one for **20 minutes** and another for **20 seconds**
- Play, pause, restart, and resume functionality for timers
- Notifications to remind users to take breaks and to start work
- **Schedule Tab**: Allows users to define custom start and end times
- **Dark Theme**: Enhanced visual comfort for night-time use
- **Custom Settings Button**: Utilizes FontAwesome to invoke the Eye Protection extension using custom shortcut keys
- Enhanced styling with CSS for improved aesthetics
- Set up a testing environment to ensure all functions work properly (Testing Purpose)

## How to Use
1. Clone this repository
2. Load this extension to chrome
3. Enable the extension
2. Go to `chrome://extensions/` and enable developers mode
3. Load the extension in Chrome
4. Enable the extension

Note : For Mac Users, please enable the Alerts from system settings for your browser or else by default you won't notification for the breaks.

## For Development Purposes

### How to Test the Functionality
1. Install the dependencies by running:
```bash
npm install
```
2. Run the tests using:
```bash
npm test
```
## License
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.

157 changes: 92 additions & 65 deletions background.js
Original file line number Diff line number Diff line change
@@ -1,101 +1,111 @@
var timerInterval;
var startTime;
var elapsedTime = 0;
var isTimerRunning = false;
var firstIntervalDuration = 20 * 60 * 1000; // 20 minutes in milliseconds
var secondIntervalDuration = 10 * 1000; // 10 seconds
// background.js

// Function to start the timer
// Timer variables
let timerInterval;
let startTime;
let elapsedTime = 0;
let isTimerRunning = false;
const firstIntervalDuration = 20 * 60 * 1000; // 20 minutes in milliseconds
const secondIntervalDuration = 20 * 1000; // 20 seconds for break

// Start timer
function startTimer() {
chrome.storage.local.get(["startTime", "elapsedTime"], function(result) {
startTime = result.startTime || Date.now() + firstIntervalDuration;
chrome.storage.local.get(["startTime", "elapsedTime"], function (result) {
startTime = result.startTime || Date.now();
elapsedTime = result.elapsedTime || 0;
if (elapsedTime > 0) {
startTime += elapsedTime;
startTime = Date.now() - elapsedTime; // Adjust start time by elapsed time
}
timerInterval = setInterval(updateTimer, 1000);
isTimerRunning = true;
chrome.storage.local.set({ isTimerRunning: true });
});
}

// Function to pause the timer
// Pause timer
function pauseTimer() {
clearInterval(timerInterval);
isTimerRunning = false;
chrome.storage.local.set({ isTimerRunning: false, elapsedTime: elapsedTime });
}

// Function to resume the timer
// Resume timer
function resumeTimer() {
startTimer();
if (!isTimerRunning) {
startTime = Date.now() - elapsedTime;
timerInterval = setInterval(updateTimer, 1000);
isTimerRunning = true;
chrome.storage.local.set({ isTimerRunning: true });
}
}

// Function to reset the timer
// Reset timer
function resetTimer() {
clearInterval(timerInterval);
elapsedTime = 0;
chrome.storage.local.set({ startTime: Date.now() + firstIntervalDuration, elapsedTime: 0 }, function() {
startTimer();
});
isTimerRunning = false;
chrome.storage.local.set({ startTime: null, elapsedTime: 0, isTimerRunning: false });
chrome.runtime.sendMessage({ type: "updateTimer", time: formatTime(firstIntervalDuration) });
}

// Function to update the timer
// Update timer
function updateTimer() {
try {
var currentTime = Date.now();
elapsedTime = startTime - currentTime;
if (elapsedTime <= 0) {
clearInterval(timerInterval);
// Send message to popup to show alert
chrome.runtime.sendMessage({ type: "updateTimer", time: "00:00:00" });
chrome.notifications.create("breakTimeNotification", {
type: "basic",
iconUrl: "images/hourglass.png",
title: "Take a break!",
message: "It's time to take a break. Look at something 20 feet away for 20 seconds."
});
// Start short break timer
startShortTimer();
} else {
// Send message to popup to update timer display
chrome.runtime.sendMessage({ type: "updateTimer", time: formatTime(elapsedTime) });
}
} catch (error) {
console.error(error);
const currentTime = Date.now();
elapsedTime = currentTime - startTime;
const remainingTime = firstIntervalDuration - elapsedTime;

if (remainingTime <= 0) {
clearInterval(timerInterval);
chrome.runtime.sendMessage({ type: "updateTimer", time: "00:00" });
notifyBreakTime();
startShortTimer();
} else {
chrome.runtime.sendMessage({ type: "updateTimer", time: formatTime(remainingTime) });
}
}

// Function to start the short break timer
function startShortTimer() {
startTime = Date.now() + secondIntervalDuration;
timerInterval = setInterval(updateShortTimer, 1000);
// Format time function
function formatTime(time) {
const minutes = Math.floor(time / 60000);
const seconds = Math.floor((time % 60000) / 1000);
return `${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
}

// Function to update the short break timer
function updateShortTimer() {
var currentTime = Date.now();
elapsedTime = startTime - currentTime;
if (elapsedTime <= 0) {
clearInterval(timerInterval);
resetTimer();
}
// Function to notify break time
function notifyBreakTime() {
chrome.runtime.sendMessage({ type: "breakTimeNotification"});
}

// Function to format time
function formatTime(time) {
var seconds = Math.floor((time / 1000) % 60);
var minutes = Math.floor((time / 1000 / 60) % 60);
var hours = Math.floor((time / 1000 / 60 / 60) % 24);
// Function to start short break timer
function startShortTimer() {
startTime = Date.now();
timerInterval = setInterval(() => {
const elapsedBreakTime = Date.now() - startTime;
const remainingBreakTime = secondIntervalDuration - elapsedBreakTime;

var formattedSeconds = seconds.toString().padStart(2, "0");
var formattedMinutes = minutes.toString().padStart(2, "0");
var formattedHours = hours.toString().padStart(2, "0");
if (remainingBreakTime <= 0) {
clearInterval(timerInterval);
chrome.runtime.sendMessage({ type: "updateTimer", time: formatTime(firstIntervalDuration) });
notifyBreakEnd();
} else {
chrome.runtime.sendMessage({ type: "updateTimer", time: formatTime(remainingBreakTime) });
}
}, 1000);
}

return formattedHours + ":" + formattedMinutes + ":" + formattedSeconds;
// Function to notify break end
function notifyBreakEnd() {
chrome.notifications.create("breakEndNotification", {
type: "basic",
iconUrl: "images/hourglass.png",
title: "Break time over",
message: "Time to get back to work! The 20-20-20 timer will restart."
});
startTimer();
}

// Listen for messages from popup script
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
console.log(message);
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
switch (message.type) {
case "startTimer":
startTimer();
Expand All @@ -110,8 +120,25 @@ chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
resetTimer();
break;
case "getTimerState":
sendResponse({ isTimerRunning: isTimerRunning, elapsedTime: elapsedTime });
chrome.runtime.sendMessage({ type: "updateTimer", time: formatTime(elapsedTime) });
break;
chrome.storage.local.get(["isTimerRunning", "elapsedTime"], function (result) {
sendResponse({
isTimerRunning: result.isTimerRunning || false,
elapsedTime: result.elapsedTime || 0
});
});
return true; // asynchronous response
}
});

// Initialization
chrome.runtime.onInstalled.addListener(() => {
resetTimer();
});

// Listen for keyboard shortcuts
chrome.commands.onCommand.addListener((command) => {
if (command === "activate_extension") {
console.log("Extension Activated"); // Log for debugging
chrome.action.openPopup(); // Open the extension popup
}
});
8 changes: 8 additions & 0 deletions content_script.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,13 @@ function executeTwentyTwentyTwentyRule() {
}
}

// Listen for changes to the eye protection state
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message.type === "enableEyeProtection") {
executeTwentyTwentyTwentyRule();
} else if (message.type === "disableEyeProtection") {
}
});

// Execute the 20-20-20 rule when the page finishes loading
window.addEventListener('load', executeTwentyTwentyTwentyRule);
35 changes: 28 additions & 7 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,44 @@
"manifest_version": 3,
"name": "EyeProtection",
"version": "1.0",
"description": "Chrome extension that implements the 20 20 20 rule",
"description": "An extension to protect your eyes with the 20-20-20 rule and customizable schedules.",
"permissions": [
"tabs",
"activeTab",
"storage",
"notifications"
"notifications",
"tabs",
"activeTab"
],
"action": {
"default_popup": "popup.html"
"default_popup": "popup.html",
"default_icon": {
"16": "images/hourglass.png",
"48": "images/hourglass.png",
"128": "images/hourglass.png"
},
"default_title": "Eye Protection Timer"
},
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content_script.js"]
"js": ["content_script.js"]
}
],
"icons": {
"16": "images/hourglass.png",
"48": "images/hourglass.png",
"128": "images/hourglass.png"
},
"commands": {
"activate_extension": {
"suggested_key": {
"default": "Ctrl+E",
"mac": "Command+E"
},
"description": "Activate the extension"
}
]
},
"options_page": "options.html"
}
Loading

0 comments on commit a68c9dd

Please sign in to comment.