├── .cursorrules ├── .gitignore ├── LICENSE ├── README.md ├── assets ├── icons │ ├── connect-128.png │ ├── connect-16.png │ ├── connect-32.png │ ├── connect-48.png │ ├── disconnect-128.png │ ├── disconnect-16.png │ ├── disconnect-32.png │ └── disconnect-48.png ├── promo-image │ ├── marquee-promo-tile.png │ └── small-promo-tile.png └── screenshots │ ├── screenshots-0.png │ ├── screenshots-1.png │ └── screenshots-2.png ├── background.js ├── manifest.json └── scripts └── package.sh /.cursorrules: -------------------------------------------------------------------------------- 1 | # Chrome Image Blocker 2 | 3 | ## Repository Overview 4 | This repository contains a Chrome extension designed to block images on webpages with a simple click. The extension helps reduce distractions and improve page load times by controlling when images are displayed. 5 | 6 | ## Purpose 7 | The main purpose of this extension is to: 8 | - Block or show images with a single click on the extension icon 9 | - Provide a quick visual indicator of the current state (images allowed or blocked) 10 | - Improve browsing experience by reducing visual distractions 11 | - Increase page load speed by preventing image loading 12 | 13 | ## Repository Structure 14 | - `manifest.json`: Chrome extension configuration file 15 | - `background.js`: Core service worker implementation of the extension 16 | - `assets/`: Icons and resources for the extension 17 | - `icons/`: Icons for the extension UI 18 | - `connect.png`: Icon for the connected state (images allowed) 19 | - `disconnect.png`: Icon for the disconnected state (images blocked) 20 | - `screenshots/`: Example screenshots showing the extension in action 21 | - Contains examples from YouTube and Instagram 22 | - `promo-image/`: Marketing images for the Chrome Web Store 23 | - `scripts/`: Utility scripts for development and deployment 24 | - `package.sh`: Script to package the extension into a ZIP file for Chrome Web Store submission 25 | - `icon.png`: Extension icon displayed in Chrome toolbar 26 | - `LICENSE`: MIT license file 27 | - `README.md`: Documentation and installation instructions 28 | 29 | ## Key Features 30 | - One-click toggle to enable/disable images instantly 31 | - Visual indicator of current state through icon changes 32 | - Simple, lightweight interface 33 | - No setup required 34 | 35 | ## Installation 36 | 1. Clone the repository 37 | 2. Load as unpacked extension in Chrome's developer mode 38 | 3. Or install from the Chrome Web Store (if published) 39 | 40 | ## Packaging for Chrome Web Store 41 | To package the extension for submission to the Chrome Web Store: 42 | 1. Run the packaging script: `./scripts/package.sh` 43 | 2. The script will create a `dist/extension.zip` file containing all necessary files 44 | 3. Upload this ZIP file to the Chrome Web Store Developer Dashboard 45 | 46 | ## Development Guidelines 47 | - Maintain the simple, clean UI design 48 | - Keep performance impact minimal 49 | - Follow Chrome extension best practices 50 | - Test thoroughly on various websites -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore node_modules directory 2 | node_modules/ 3 | 4 | # Ignore build output directories 5 | dist/ 6 | build/ 7 | 8 | # Ignore log files 9 | *.log 10 | 11 | # Ignore environment variable files 12 | .env 13 | .env.local 14 | 15 | # Ignore OS specific files 16 | .DS_Store 17 | Thumbs.db 18 | 19 | # Ignore IDE specific files 20 | .vscode/ 21 | .idea/ 22 | *.swp 23 | 24 | # Ignore test coverage reports 25 | coverage/ 26 | 27 | # Ignore npm debug files 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | 32 | repo-to-text_*.txt 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Kirill Markin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chrome Image Blocker 2 | 3 | ## Repository Overview 4 | This repository contains a Chrome extension designed to block images on webpages with a simple click. The extension helps reduce distractions and improve page load times by controlling when images are displayed. 5 | 6 | ## Purpose 7 | The main purpose of this extension is to: 8 | - Block or show images with a single click on the extension icon 9 | - Provide a quick visual indicator of the current state (images allowed or blocked) 10 | - Improve browsing experience by reducing visual distractions 11 | - Increase page load speed by preventing image loading 12 | 13 | ## Repository Structure 14 | - `manifest.json`: Chrome extension configuration file 15 | - `background.js`: Core service worker implementation of the extension 16 | - `assets/`: Icons and resources for the extension 17 | - `icons/`: Icons for the extension UI 18 | - `connect.png`: Icon for the connected state (images allowed) 19 | - `disconnect.png`: Icon for the disconnected state (images blocked) 20 | - `screenshots/`: Example screenshots showing the extension in action 21 | - Contains examples from YouTube and Instagram 22 | - `promo-image/`: Marketing images for the Chrome Web Store 23 | - `scripts/`: Utility scripts for development and deployment 24 | - `package.sh`: Script to package the extension into a ZIP file for Chrome Web Store submission 25 | - `icon.png`: Extension icon displayed in Chrome toolbar 26 | - `LICENSE`: MIT license file 27 | - `README.md`: Documentation and installation instructions 28 | 29 | ## Key Features 30 | - One-click toggle to enable/disable images instantly 31 | - Visual indicator of current state through icon changes 32 | - Simple, lightweight interface 33 | - No setup required 34 | 35 | ## Installation 36 | 1. Clone the repository 37 | 2. Load as unpacked extension in Chrome's developer mode 38 | 3. Or install from the Chrome Web Store (if published) 39 | 40 | ## Packaging for Chrome Web Store 41 | To package the extension for submission to the Chrome Web Store: 42 | 1. Run the packaging script: `./scripts/package.sh` 43 | 2. The script will create a `dist/extension.zip` file containing all necessary files 44 | 3. Upload this ZIP file to the Chrome Web Store Developer Dashboard 45 | 46 | ## How to Use 47 | 1. Click the extension icon in your Chrome toolbar to toggle images on or off 48 | 2. The icon will change to indicate the current state: 49 | - Connected icon: Images are allowed 50 | - Disconnected icon: Images are blocked 51 | 52 | ## Development Guidelines 53 | - Maintain the simple, clean UI design 54 | - Keep performance impact minimal 55 | - Follow Chrome extension best practices 56 | - Test thoroughly on various websites 57 | 58 | ## Screenshots 59 | 60 | | ![YouTube example](/assets/screenshots/screenshots-1.png) | ![Instagram example](/assets/screenshots/screenshots-2.png) | 61 | |:---------------------------------------------:|:---------------------------------------------:| 62 | | YouTube example | Instagram example | 63 | 64 | ## Features 65 | 66 | - Toggles images on or off with a single click 67 | - Visual feedback through icon changes 68 | - Simple, intuitive interface 69 | - No configuration needed 70 | - Lightweight and efficient 71 | 72 | ## How It Works 73 | 74 | This extension changes Chrome's image settings to block or allow images with a single click. The extension icon updates to visually indicate whether images are currently allowed or blocked. 75 | 76 | ## Contributing 77 | 78 | Contributions are welcome! Please open an issue or submit a pull request. 79 | 80 | ## License 81 | 82 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. 83 | 84 | ## Contact 85 | 86 | If you have any questions, feel free to contact me at [markinkirill@gmail.com](mailto:markinkirill@gmail.com). 87 | 88 | ## Authors 89 | 90 | This extension was created by 91 | - [Kirill Markin](https://kirill-markin.com/) 92 | - [Maria Podobrazhnykh](https://www.linkedin.com/in/maria-podobrazhnykh/) 93 | - [Andrey Markin](https://andrey-markin.com/) 94 | -------------------------------------------------------------------------------- /assets/icons/connect-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/icons/connect-128.png -------------------------------------------------------------------------------- /assets/icons/connect-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/icons/connect-16.png -------------------------------------------------------------------------------- /assets/icons/connect-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/icons/connect-32.png -------------------------------------------------------------------------------- /assets/icons/connect-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/icons/connect-48.png -------------------------------------------------------------------------------- /assets/icons/disconnect-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/icons/disconnect-128.png -------------------------------------------------------------------------------- /assets/icons/disconnect-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/icons/disconnect-16.png -------------------------------------------------------------------------------- /assets/icons/disconnect-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/icons/disconnect-32.png -------------------------------------------------------------------------------- /assets/icons/disconnect-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/icons/disconnect-48.png -------------------------------------------------------------------------------- /assets/promo-image/marquee-promo-tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/promo-image/marquee-promo-tile.png -------------------------------------------------------------------------------- /assets/promo-image/small-promo-tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/promo-image/small-promo-tile.png -------------------------------------------------------------------------------- /assets/screenshots/screenshots-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/screenshots/screenshots-0.png -------------------------------------------------------------------------------- /assets/screenshots/screenshots-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/screenshots/screenshots-1.png -------------------------------------------------------------------------------- /assets/screenshots/screenshots-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirill-markin/chrome-auto-image-blocker/8ce7e5f97e64bc22d4f105305275b6fdb69c432c/assets/screenshots/screenshots-2.png -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | // Utility functions 2 | async function getImageSettingForPattern(pattern) { 3 | return new Promise((resolve, reject) => { 4 | chrome.contentSettings.images.get({ primaryUrl: pattern }, (details) => { 5 | if (chrome.runtime.lastError) { 6 | console.error( 7 | `Error getting current setting for ${pattern}:`, 8 | chrome.runtime.lastError.message 9 | ); 10 | reject(chrome.runtime.lastError); 11 | } else if (details) { 12 | resolve(details.setting); 13 | } else { 14 | console.error(`Failed to get current setting details for ${pattern}.`); 15 | reject(new Error("No details found")); 16 | } 17 | }); 18 | }); 19 | } 20 | 21 | async function getCurrentSetting() { 22 | const patterns = ["http://*/*", "https://*/*"]; 23 | try { 24 | const results = await Promise.all(patterns.map(getImageSettingForPattern)); 25 | return results[0]; // Assuming all patterns have the same setting 26 | } catch (error) { 27 | console.error("Error getting current setting:", error); 28 | return "allow"; // Default to allow if there's an error 29 | } 30 | } 31 | 32 | // Set images setting (allow or block) 33 | async function setImagesSetting(setting) { 34 | const patterns = ["http://*/*", "https://*/*"]; 35 | const settingPromises = patterns.map(pattern => { 36 | return new Promise((resolve, reject) => { 37 | chrome.contentSettings.images.set( 38 | { 39 | primaryPattern: pattern, 40 | setting: setting, 41 | }, 42 | () => { 43 | if (chrome.runtime.lastError) { 44 | console.error( 45 | `Error setting new setting for ${pattern}:`, 46 | chrome.runtime.lastError.message 47 | ); 48 | reject(chrome.runtime.lastError); 49 | } else { 50 | resolve(); 51 | } 52 | } 53 | ); 54 | }); 55 | }); 56 | 57 | try { 58 | await Promise.all(settingPromises); 59 | console.log(`Images are now ${setting === "allow" ? "allowed" : "blocked"}.`); 60 | 61 | // Save the current state to storage 62 | chrome.storage.sync.set({ imagesSetting: setting }, () => { 63 | if (chrome.runtime.lastError) { 64 | console.error( 65 | "Error saving images setting:", 66 | chrome.runtime.lastError.message 67 | ); 68 | } 69 | }); 70 | 71 | // Update icon based on current state 72 | updateIcon(setting); 73 | 74 | return true; 75 | } catch (error) { 76 | console.error("Error setting images setting:", error); 77 | return false; 78 | } 79 | } 80 | 81 | // Toggle images setting 82 | async function toggleImagesSetting() { 83 | try { 84 | const currentSetting = await getCurrentSetting(); 85 | const newSetting = currentSetting === "allow" ? "block" : "allow"; 86 | const success = await setImagesSetting(newSetting); 87 | if (success) { 88 | refreshCurrentTab(); 89 | } 90 | } catch (error) { 91 | console.error("Error toggling images setting:", error.message); 92 | } 93 | } 94 | 95 | // Refresh the current tab using tabs.reload 96 | function refreshCurrentTab() { 97 | chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { 98 | if (tabs.length > 0) { 99 | const tabId = tabs[0].id; 100 | chrome.tabs.reload(tabId); 101 | } 102 | }); 103 | } 104 | 105 | // Update the extension icon based on current setting 106 | function updateIcon(setting) { 107 | const iconPath = setting === "allow" ? 108 | { 109 | path: { 110 | "16": "assets/icons/disconnect-16.png", 111 | "32": "assets/icons/disconnect-32.png", 112 | "48": "assets/icons/disconnect-48.png", 113 | "128": "assets/icons/disconnect-128.png" 114 | } 115 | } : 116 | { 117 | path: { 118 | "16": "assets/icons/connect-16.png", 119 | "32": "assets/icons/connect-32.png", 120 | "48": "assets/icons/connect-48.png", 121 | "128": "assets/icons/connect-128.png" 122 | } 123 | }; 124 | 125 | chrome.action.setIcon(iconPath, () => { 126 | if (chrome.runtime.lastError) { 127 | console.error("Icon error details:", chrome.runtime.lastError); 128 | console.log("Attempted to set icon with path:", JSON.stringify(iconPath)); 129 | } else { 130 | console.log("Icon successfully updated to:", setting === "allow" ? "disconnect" : "connect"); 131 | } 132 | }); 133 | } 134 | 135 | // Apply saved images setting on startup 136 | async function applySavedImagesSetting() { 137 | chrome.storage.sync.get(["imagesSetting"], async (result) => { 138 | const setting = result.imagesSetting || "allow"; // Default to 'allow' if not set 139 | await setImagesSetting(setting); 140 | }); 141 | } 142 | 143 | // Event listeners 144 | chrome.runtime.onInstalled.addListener(() => { 145 | console.log("Extension installed or reloaded"); 146 | applySavedImagesSetting(); 147 | }); 148 | 149 | chrome.runtime.onStartup.addListener(() => { 150 | console.log("Browser startup"); 151 | applySavedImagesSetting(); 152 | }); 153 | 154 | // Listen for browser action clicks 155 | chrome.action.onClicked.addListener(() => { 156 | console.log("Extension icon clicked, toggling images setting"); 157 | toggleImagesSetting(); 158 | }); 159 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "name": "Image Blocker", 4 | "version": "2.1", 5 | "description": "Toggle images on websites with a single click. Reduce distractions and improve page load times with this simple image blocker.", 6 | "permissions": ["activeTab", "storage", "contentSettings"], 7 | "background": { 8 | "service_worker": "background.js" 9 | }, 10 | "action": { 11 | "default_icon": { 12 | "16": "assets/icons/disconnect-16.png", 13 | "32": "assets/icons/disconnect-32.png", 14 | "48": "assets/icons/disconnect-48.png", 15 | "128": "assets/icons/disconnect-128.png" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scripts/package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script to package Chrome extension for submission to the Chrome Web Store 4 | # Created for chrome-auto-image-blocker 5 | 6 | echo "🔧 Packaging Chrome extension for Web Store submission..." 7 | 8 | # Set variables 9 | OUTPUT_ZIP="extension.zip" 10 | OUTPUT_DIR="dist" 11 | 12 | # Create dist directory if it doesn't exist 13 | mkdir -p $OUTPUT_DIR 14 | 15 | # Remove existing zip file if it exists 16 | if [ -f "$OUTPUT_DIR/$OUTPUT_ZIP" ]; then 17 | echo "🗑️ Removing existing package..." 18 | rm "$OUTPUT_DIR/$OUTPUT_ZIP" 19 | fi 20 | 21 | # Create new zip file with only the required files 22 | echo "📦 Creating new package with required files..." 23 | zip -r "$OUTPUT_DIR/$OUTPUT_ZIP" manifest.json background.js assets/icons -x "*.DS_Store" "*.git*" "*.swp" "._*" 24 | 25 | # Display result 26 | if [ $? -eq 0 ]; then 27 | echo "✅ Package created successfully at $OUTPUT_DIR/$OUTPUT_ZIP" 28 | echo "📏 Package size: $(du -h "$OUTPUT_DIR/$OUTPUT_ZIP" | cut -f1)" 29 | echo "🌐 Ready for Chrome Web Store submission!" 30 | else 31 | echo "❌ Failed to create package" 32 | exit 1 33 | fi --------------------------------------------------------------------------------