diff --git a/submissions/securePhotos/README.md b/submissions/securePhotos/README.md new file mode 100644 index 00000000..2ce62a47 --- /dev/null +++ b/submissions/securePhotos/README.md @@ -0,0 +1,83 @@ +# PhotoLancer +***PhotoLancer*** enhances your browsing experience by unblurring and displaying high-quality images in modern galleries on platforms like **Google Photos**. πŸš€ + +--- + +### πŸ“Έ **PhotoLancer – Unblur & Enhance Image Galleries** +> **A modern Chrome extension that unblurs images and enhances gallery views on Google Photos and Facebook.** + + +--- + +## πŸš€ **Features** +βœ… **Unblur Images Instantly** – View high-quality images effortlessly. +βœ… **Smart Positioning** – The preview modal appears in the best position to avoid cropping. +βœ… **Supports Google Photos & Facebook** – Works with dynamically loaded images. +βœ… **Beautiful Glass UI** – A sleek, modern design with smooth animations. +βœ… **Optimized for Performance** – Runs efficiently without slowing down browsing. + +--- + +## πŸ›  **Installation Guide** +### **πŸ”Ή Manual Installation (For Developers & Testing)** +1. **Download the repository** + ```sh + https://github.com/0mahi11/PhotoLancer.git + ``` +2. **Open Chrome** and go to `chrome://extensions/`. +3. **Enable Developer Mode** (top right corner). +4. **Click "Load Unpacked"** and select the extension folder. +5. **Done!** Your extension is now running! πŸŽ‰ + +### **πŸ”Ή Chrome Web Store (Coming Soon)** +Once published, you’ll be able to install it from the [Chrome Web Store](#). + +--- + +## πŸ“– **How It Works** +1. **Hover over a blurred image** – The extension detects it automatically. +2. **A high-quality preview appears** – Unblurred and well-positioned. +3. **Move away to hide** – The modal smoothly disappears. + +--- + +## πŸ–₯ **Supported Platforms** +βœ… **Google Photos** +βœ… **Facebook** (Profile pictures, cover images, and more) +βœ… **More platforms coming soon!** + +--- + +## πŸ’» **Technical Details** +### **πŸ”Ή File Structure** +``` +πŸ“‚ PhotoLancer/ +β”œβ”€β”€ πŸ“œ manifest.json # Chrome extension configuration +β”œβ”€β”€ πŸ“œ content.js # Core script handling image unblurring +β”œβ”€β”€ 🎨 styles.css # Modern UI styles +β”œβ”€β”€ πŸ“œ README.md # This documentation +└── πŸ“‚ icons/ # Extension icons (optional) +``` + +### **πŸ”Ή Technologies Used** +- **JavaScript** – For handling dynamic images & DOM updates +- **CSS** – Glass UI with smooth animations +- **MutationObserver** – Detects dynamically loaded images (e.g., Facebook) + +--- + +## πŸ›  **Contributing** +We welcome contributions! πŸš€ +1. Fork the repo +2. Create a new branch (`git checkout -b feature-name`) +3. Make your changes +4. Push and submit a PR + +--- + +## βš– **License** +**PhotoLancer** is **open-source** under the **MIT License**. + +--- + +πŸ”₯ **Enjoy browsing without blur!** πŸš€ diff --git a/submissions/securePhotos/content.js b/submissions/securePhotos/content.js new file mode 100644 index 00000000..0a668fa6 --- /dev/null +++ b/submissions/securePhotos/content.js @@ -0,0 +1,117 @@ +(function () { + const modal = document.createElement("div"); + modal.id = "unblur-modal"; + Object.assign(modal.style, { + position: "absolute", + display: "none", + zIndex: "10000", + padding: "15px", + background: "rgba(255, 255, 255, 0.95)", // Soft glass effect + boxShadow: "0 15px 40px rgba(0,0,0,0.3)", + backdropFilter: "blur(10px)", + borderRadius: "12px", + transition: "opacity 0.3s ease, transform 0.3s ease", + transform: "scale(0.9)", + overflow: "hidden", + display: "flex", + justifyContent: "center", + alignItems: "center", + border: "1px solid rgba(255, 255, 255, 0.2)", + }); + document.body.appendChild(modal); + + function getImageSource(target) { + // Standard sites (Google Images, etc.) + let child = target.querySelector("div.RY3tic[data-latest-bg]"); + if (child) return child.getAttribute("data-latest-bg"); + + // Facebook images (supports newer DOM structure) + let fbImg = target.querySelector("img[src]"); + if (fbImg) return fbImg.src; + + return null; + } + + function showModal(target) { + modal.innerHTML = ""; + const imgSrc = getImageSource(target); + + if (imgSrc) { + const img = document.createElement("img"); + img.src = imgSrc; + + Object.assign(img.style, { + filter: "none", + width: "100%", + height: "100%", + borderRadius: "8px", + display: "block", + objectFit: "cover", // Ensures image fills the modal + maxWidth: "100%", + maxHeight: "100%", + boxShadow: "0 6px 20px rgba(0,0,0,0.2)", + }); + + modal.appendChild(img); + + // Get target image size + const rect = target.getBoundingClientRect(); + const imgWidth = rect.width; + const imgHeight = rect.height; + + // Set modal size relative to the image + const modalWidth = Math.min(imgWidth * 1.2, 600); // Scale but cap at 600px + const modalHeight = Math.min(imgHeight * 1.2, 500); // Scale but cap at 500px + + const offset = 20; + let left = rect.left + window.scrollX + rect.width / 2 - modalWidth / 2; + let top = rect.top + window.scrollY + rect.height + offset; + + // If not enough space below, move above + if (top + modalHeight > window.innerHeight + window.scrollY) { + top = rect.top + window.scrollY - modalHeight - offset; + } + + // Ensure modal stays within viewport + if (left + modalWidth > window.innerWidth) { + left = window.innerWidth - modalWidth - 10; + } + if (left < 10) { + left = 10; + } + + // Apply position & size + modal.style.width = `${modalWidth}px`; + modal.style.height = `${modalHeight}px`; + modal.style.left = `${left}px`; + modal.style.top = `${top}px`; + modal.style.display = "flex"; + modal.style.opacity = "1"; + modal.style.transform = "scale(1)"; + } + } + + function hideModal() { + modal.style.opacity = "0"; + modal.style.transform = "scale(0.9)"; + setTimeout(() => { + modal.style.display = "none"; + }, 300); + } + + function addGalleryListeners() { + const galleryItems = document.querySelectorAll("div.rtIMgb, div.x1i10hfl"); // Google & Facebook images + galleryItems.forEach((item) => { + if (!item.dataset.hoverListenerAdded) { + item.addEventListener("mouseenter", () => showModal(item)); + item.addEventListener("mouseleave", hideModal); + item.dataset.hoverListenerAdded = "true"; + } + }); + } + + addGalleryListeners(); + + const observer = new MutationObserver(addGalleryListeners); + observer.observe(document.body, { childList: true, subtree: true }); +})(); diff --git a/submissions/securePhotos/logo.png b/submissions/securePhotos/logo.png new file mode 100644 index 00000000..a6fde5fd Binary files /dev/null and b/submissions/securePhotos/logo.png differ diff --git a/submissions/securePhotos/manifest.json b/submissions/securePhotos/manifest.json new file mode 100644 index 00000000..3ca0282a --- /dev/null +++ b/submissions/securePhotos/manifest.json @@ -0,0 +1,17 @@ +{ + "manifest_version": 3, + "name": "PhotoLancer", + "description": "Secure your photos as blur and enjoy", + "version": "1.0", + "icons": { + "128": "logo.png" + }, + "content_scripts": [ + { + "matches": ["https://photos.google.com/*"], + "js": ["content.js"], + "css": ["styles.css"] + } + ], + "permissions": [] +} diff --git a/submissions/securePhotos/styles.css b/submissions/securePhotos/styles.css new file mode 100644 index 00000000..8a8b101f --- /dev/null +++ b/submissions/securePhotos/styles.css @@ -0,0 +1,23 @@ +/* Apply blur to the gallery container tag instead of an img tag */ +div.rtIMgb { + filter: blur(5px) !important; + transition: filter 0.3s ease; + } + + /* Modern Gallery Layout: style the main photo grid as a responsive grid. + This assumes the gallery container uses role="grid" */ + div[role="grid"] { + display: grid !important; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 15px; + padding: 15px; + } + + /* Optional: give each gallery item a modern β€œcard” look */ + div[role="grid"] > div { + background: #fff; + border-radius: 8px; + overflow: hidden; + box-shadow: 0 2px 8px rgba(0,0,0,0.1); + } + \ No newline at end of file