From e3fac97c3b2ab7d419433d85bf063e66e66e073f Mon Sep 17 00:00:00 2001 From: theliendem Date: Mon, 17 Mar 2025 17:03:25 -0400 Subject: [PATCH 1/6] Create README.md --- submissions/Tabloid/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 submissions/Tabloid/README.md diff --git a/submissions/Tabloid/README.md b/submissions/Tabloid/README.md new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/submissions/Tabloid/README.md @@ -0,0 +1 @@ + From 26487424f247af6bf1c6e8a1b46f48dd13c3b194 Mon Sep 17 00:00:00 2001 From: theliendem Date: Mon, 17 Mar 2025 17:03:45 -0400 Subject: [PATCH 2/6] Add files via upload --- submissions/Tabloid/background.js | 204 ++++++++++++ submissions/Tabloid/manifest.json | 38 +++ submissions/Tabloid/popup.html | 105 ++++++ submissions/Tabloid/popup.js | 509 ++++++++++++++++++++++++++++++ 4 files changed, 856 insertions(+) create mode 100644 submissions/Tabloid/background.js create mode 100644 submissions/Tabloid/manifest.json create mode 100644 submissions/Tabloid/popup.html create mode 100644 submissions/Tabloid/popup.js diff --git a/submissions/Tabloid/background.js b/submissions/Tabloid/background.js new file mode 100644 index 00000000..2230f64d --- /dev/null +++ b/submissions/Tabloid/background.js @@ -0,0 +1,204 @@ +const storageAPI = chrome.storage; +const api = chrome; + +function getDomain(url) { + try { + return new URL(url).hostname.replace("www.", "").split(".").slice(-2).join("."); + } catch (e) { + return null; + } +} + +function checkDomain(tabId, url) { + if (url.startsWith("chrome-extension://") || url.startsWith("chrome://")) return console.log("Tab-buse: Ignoring extension page"); + + const domain = getDomain(url); + if (!domain) return; + + storageAPI.local.get(["categorizedDomains", "ignoredDomains"], (data) => { + const categorized = data.categorizedDomains || {}; + const ignored = data.ignoredDomains || {}; + + if (categorized[domain] || ignored[domain]) return; + + promptUserToCategorize(tabId, domain); + }); +} + +function promptUserToCategorize(tabId, domain) { + // chrome.scripting.executeScript({ + // target: { tabId }, + // function: showCategorizationPromptUI, + // args: [domain] + // }); + + chrome.scripting.executeScript({ + target: { tabId: tabId }, + func: showCategorizationPromptUI, + args: [domain] + }).catch((err) => { + console.error("Error injecting script: ", err); + }) +} + +function showCategorizationPromptUI(domain) { + // Check if a prompt already exists + if (document.getElementById("tabbuse-prompt")) return; + + // Create the popup container + const popup = document.createElement("div"); +// popup.innerHTML = ``` +// +// +// ```; + + const fontLink = document.createElement("div"); + fontLink.innerHTML = ``; + document.head.appendChild(fontLink); + + popup.id = "tabbuse-prompt"; + popup.style.position = "fixed"; + popup.style.top = "10px"; + popup.style.right = "10px"; + popup.style.background = "lightgray"; + popup.style.border = "2px solid #333"; + popup.style.borderRadius = "10px"; + popup.style.boxShadow = "10px 4px 6px rgba(0,0,0,1)"; + popup.style.fontFamily = "\"Inter\", Calibri, Verdana, Arial, sans-serif"; + popup.style.paddingTop = "30px"; + popup.style.paddingBottom = "30px"; + popup.style.paddingLeft = "20px"; + popup.style.paddingRight = "40px"; + popup.style.maxWidth = "30%"; + popup.style.zIndex = "9999"; + popup.style.boxShadow = "0px 4px 6px rgba(0,0,0,0.1)"; + popup.style.color = "black !important"; + + // Title + popup.innerHTML += `Categorize ${domain}

`; + + // Dropdown for existing categories + const categorySelect = document.createElement("select"); + categorySelect.innerHTML = ``; + categorySelect.style.color = "black"; + categorySelect.style.padding = "5px"; + categorySelect.style.marginTop = "5px"; + + // Fetch existing categories from storage + chrome.storage.local.get(["categorizedDomains"], (data) => { + const categories = new Set(Object.values(data.categorizedDomains || {})); + categories.forEach(cat => { + const option = document.createElement("option"); + option.value = cat; + option.textContent = cat; + option.style.color = "black"; + categorySelect.appendChild(option); + }); + }); + + popup.appendChild(categorySelect); + popup.appendChild(document.createElement("br")); + + // Input for new category + const categoryInput = document.createElement("input"); + categoryInput.type = "text"; + categoryInput.placeholder = "Or enter a new category"; + categoryInput.style.color = "gray"; + categoryInput.style.border = "none"; + categoryInput.style.borderBottom = "2px solid deepskyblue"; + categoryInput.style.backgroundColor = "lightgray"; + categoryInput.style.padding = "5px"; + categoryInput.style.marginTop = "7px"; + categoryInput.style.marginBottom = "7px"; + popup.appendChild(categoryInput); + popup.appendChild(document.createElement("br")); + + // "Never ask again" checkbox + const neverAskCheckbox = document.createElement("input"); + neverAskCheckbox.type = "checkbox"; + neverAskCheckbox.id = "never-ask-again"; + neverAskCheckbox.style.marginTop = "5px"; + neverAskCheckbox.style.cursor = "pointer"; + neverAskCheckbox.style.color = "black"; + + const label = document.createElement("label"); + label.textContent = " Never ask again"; + label.htmlFor = "never-ask-again"; + label.style.marginLeft = "5px"; + label.style.color = "black"; + label.style.marginBottom = "10px"; + + popup.appendChild(neverAskCheckbox); + popup.appendChild(label); + popup.appendChild(document.createElement("br")); + + // Save button + const saveButton = document.createElement("button"); + saveButton.textContent = "Save"; + saveButton.style.marginTop = "5px"; + saveButton.style.cursor = "pointer"; + saveButton.style.color = "black"; + saveButton.style.backgroundColor = "deepskyblue"; + saveButton.style.border = "none"; + saveButton.style.padding = "5px 15px"; + saveButton.style.borderRadius = "5px"; + saveButton.style.marginRight = "5px"; + popup.appendChild(saveButton); + + // Cancel button + const cancelButton = document.createElement("button"); + cancelButton.textContent = "Cancel"; + cancelButton.style.marginTop = "5px"; + cancelButton.style.marginLeft = "5px"; + cancelButton.style.cursor = "pointer"; + cancelButton.style.color = "black"; + cancelButton.style.backgroundColor = "deepskyblue"; + cancelButton.style.border = "none"; + cancelButton.style.padding = "5px 15px"; + cancelButton.style.borderRadius = "5px"; + cancelButton.style.marginRight = "5px"; + popup.appendChild(cancelButton); + + document.body.appendChild(popup); + + // Handle Save + saveButton.addEventListener("click", () => { + const selectedCategory = categorySelect.value; + const newCategory = categoryInput.value.trim(); + const neverAskAgain = neverAskCheckbox.checked; + + chrome.storage.local.get(["categorizedDomains", "ignoredDomains"], (data) => { + let categorized = data.categorizedDomains || {}; + let ignored = data.ignoredDomains || {}; + + if (newCategory) { + categorized[domain] = newCategory; + } else if (selectedCategory) { + categorized[domain] = selectedCategory; + } else if (neverAskAgain) { + ignored[domain] = true; + } + + chrome.storage.local.set({ categorizedDomains: categorized, ignoredDomains: ignored }, () => { + console.log(`Successfully categorized ${domain}`); + }); + }); + + popup.remove(); + }); + + // Handle Cancel + cancelButton.addEventListener("click", () => popup.remove()); +} + +function addTabListeners() { + chrome.tabs.onCreated.addListener((tab) => { + checkDomain(tab.id, tab.url); + }); + + chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { + if (changeInfo.url) checkDomain(tabId, changeInfo.url); + }); +} + +addTabListeners(); \ No newline at end of file diff --git a/submissions/Tabloid/manifest.json b/submissions/Tabloid/manifest.json new file mode 100644 index 00000000..57792d3a --- /dev/null +++ b/submissions/Tabloid/manifest.json @@ -0,0 +1,38 @@ +{ + "manifest_version": 3, + "name": "Tabloid", + "version": "1.0.0", + "description": "An extension that roasts you based on your tab usage.", + "permissions": [ + "tabs", + "storage", + "scripting", + "activeTab" + ], + "host_permissions": [ + "", + "http://fonts.googleapis.com/", + "https://fonts.googleapis.com/" + ], + "action": { + "default_popup": "popup.html", + "default_icon": { + "16": "icons/icon16.png", + "48": "icons/icon48.png", + "128": "icons/icon128.png" + } + }, + "background": { + "service_worker": "background.js" + }, + "icons": { + "16": "icons/icon16.png", + "48": "icons/icon48.png", + "128": "icons/icon128.png" + }, + "browser_specific_settings": { + "gecko": { + "id": "tabuse@example.com" + } + } +} \ No newline at end of file diff --git a/submissions/Tabloid/popup.html b/submissions/Tabloid/popup.html new file mode 100644 index 00000000..d384af08 --- /dev/null +++ b/submissions/Tabloid/popup.html @@ -0,0 +1,105 @@ + + + + + + Tab-buse + + + + + + + + +

Welcome to the
Tabloid

+
+
+ +
+ +
+

Current Tab

+

Loading...

+ + + +
+ +
+
+ +
+ +
+
Toggle category breakdown
+ + +
+
+ +

Manage Categories

+

+ +
+
+ +
Toggle ignored domain management
+ + +


+

Made by Neil Dembla

+ + + + + + + \ No newline at end of file diff --git a/submissions/Tabloid/popup.js b/submissions/Tabloid/popup.js new file mode 100644 index 00000000..fbbc08b7 --- /dev/null +++ b/submissions/Tabloid/popup.js @@ -0,0 +1,509 @@ +// Add styles for floating modal +const style = document.createElement("style"); +style.textContent = ` + .floating-modal { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background: #FFF; + padding: 20px; + border-radius: 10px; + box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.2); + z-index: 10000; + } + .modal-content { + text-align: center; + } + button { + margin: 5px; + } +`; + +const overThirtyTabs = [ + "Your browser has more tabs open than your brain has functioning neurons. Close some before your computer files a restraining order.", + "Are you running a NASA mission, or just too lazy to bookmark? Your RAM is sobbing in the corner.", + "Your browser is one bad refresh away from a full-blown midlife crisis. Let it breathe, dude.", + "Why do you even have a search bar? You clearly believe in never finding anything again.", + "At this point, your browser isn’t opening pages, it’s assembling an encyclopedia that nobody asked for.", + "NASA called. They said even their supercomputers can’t handle this level of chaos.", + "You have more tabs open than a conspiracy theorist with a Red Bull addiction. Seek help.", + "Your computer fans are working harder than you. Close some tabs before your laptop turns into a space heater.", + "Congratulations! You’ve successfully turned your browser into a digital landfill. Hope you enjoy digging for that one tab from last Tuesday.", + "You’ve got more tabs than a hoarder has expired coupons.", + "If tabs were brain cells, you’d be a genius. Too bad none of them are actually useful.", + "Even Google is judging you right now. And Google sees everything.", + "You’re one tab away from being the person who accidentally starts a cyber apocalypse.", + "Your browser is a digital manifestation of your life: chaotic, disorganized, and full of regret.", + "You’re the reason the ‘close all tabs’ button was invented.", + "I’ve seen cleaner disasters at nuclear waste sites. What are you even doing with this many tabs?", + "You’ve got more tabs than the average office has excuses for not working.", + "I’ve seen more organized chaos in a toddler’s toy bin than in your browser window" +]; +const overTwentyTabs = [ + "Your tab bar is smaller than your attention span. Close some tabs before your browser files for divorce.", + "How do you even function? Your tabs look like a digital hoarder’s wet dream.", + "Your CPU just left a resignation letter. It refuses to work under these conditions.", + "You’re one tab away from your browser spontaneously combusting. And honestly, I’d support it.", + "Your search history must be a horror movie, but this tab list? This is the real nightmare.", + "If I had to open as many tabs as you, I’d rather open my own grave.", + "The only thing more chaotic than your tab list is your decision-making process.", + "How many tabs do you need open before you realize your brain is the one that’s frozen?", + "Your browser’s memory is giving up on life because it can’t handle the weight of your bad choices.", + "If you opened as many opportunities in life as you do tabs, maybe you’d have a career by now.", + "You’re the human embodiment of ‘too many cooks in the kitchen’—except it’s just browser tabs, and none of them know what they’re doing.", + "You’re the only person who needs a browser extension to remind you that you need help.", + "You could probably launch a startup with the number of tabs you’ve got open, but it would crash faster than your attention span." +]; +const tooFewTabs = [ + "Your browser’s looking a little empty. Did you forget how to internet, grandma?", + "Your browser looks like a deserted wasteland—are you even using the internet, or just staring at the homepage?", + "Your browser history must be the shortest story ever written.", + "Are you afraid of commitment, or do you just not have enough thoughts to need multiple tabs?", + "You have fewer tabs open than a tech-illiterate grandparent. Next step: asking how to copy and paste?", + "Your browser’s emptier than a library on a Friday night. What are you even doing with your life?", + "With so few tabs open, your computer must think it’s retired. Give it something to do before it starts collecting social security.", + "Your browser’s emptier than a politician’s promises. What are you even doing with your life?", + "Minimalist? More like mentally unprepared for anything beyond a single Google search.", + "Your browser is so empty, even the ‘New Tab’ page looks bored.", + "With so few tabs open, I bet you still type full URLs instead of using bookmarks.", + "Are you really using the internet, or just giving your computer something to do between naps?", + "Having this few tabs open should be a crime against curiosity.", + "With that few tabs, you must be one of those people who actually closes their apps instead of letting them pile up.", + "Blink twice if you don’t know what Ctrl+T does." +]; +const shoppingRoasts = [ + "How many tabs does it take for you to realize that your shopping cart isn’t a personal achievement ?", + "If your shopping tabs were any more stacked, they’d need their own storage unit.", + "Your browser’s been open longer than those ‘limited-time offers’ you’ve been ignoring.", + "Your tabs are like a digital shopping cart that’s been abandoned in the middle of the store.", + "Your browser’s got more tabs than a shopping mall on Black Friday.", +]; +const entertainmentRoasts = [ + "You have more tabs dedicated to streaming shows than Netflix has original content.", + "Your tabs are like a digital library that nobody asked for.", + "At this point, your browser is just a digital theater showing a never-ending rerun of your procrastination.", + "Do you have tabs open for every season of every show, or are you just pretending to catch up on life?" +]; +const productivityRoasts = [ + "You’re the kind of person who opens 12 tabs to organize their life and ends up only organizing procrastination.", + "Your tabs are like a digital to-do list that’s been ignored for weeks.", + "Your productivity tabs are the digital equivalent of making a to-do list and never crossing anything off.", + "How do you keep track of all those productivity tabs? Are you hoping one will finally organize your life for you?", + "If your work tabs were a project, they’d be the never-ending draft.", + "I’m impressed by how your browser can multitask—but maybe you should, too." +]; +const socialRoasts = [ + "I’m surprised your browser hasn’t started sending you ‘Are you still there?’ messages for all those social media tabs.", + "You’ve got enough tabs open for Instagram, Twitter, and Facebook to have a reunion.", + "How many tabs do you need to scroll through before realizing you’re just hiding from real life behind memes?" +]; + +var systemPage = false; + +function detectSystemPage(url) { + if (url.startsWith("about:") || url.startsWith("chrome-extension://") || url.startsWith("chrome://")) return true; + return false; +} + +function capitalizeFirstLetter(val) { + return String(val).charAt(0).toUpperCase() + String(val).slice(1); +} + +function categorizeTabs() { + const tabsAPI = chrome.tabs; // For Firefox + + tabsAPI.query({}, (tabs) => { + // Get all categorized domains from storage + chrome.storage.local.get(["categorizedDomains"], (data) => { + const categorized = data.categorizedDomains || {}; + const categorizedTabs = {}; + const uncategorizedTabs = []; + + tabs.forEach((tab) => { + if (tab.url.startsWith("about:") || tab.url.startsWith("moz-extension://")) return systemPage = true; + let domain = getDomain(tab.url); + const category = categorized[domain] || "Miscellaneous"; + + // if (domain == "" || domain === " ") domain = "Browser tab"; + + if (categorizedTabs[category]) categorizedTabs[category].push(domain); + else categorizedTabs[category] = [domain]; + + if (!categorized[domain]) { + uncategorizedTabs.push(domain); + } + }); + + // Show roast text based on the categorized tabs + showRoast(categorizedTabs, uncategorizedTabs.length); + + // Show the number of open tabs + showTabCount(tabs.length); + + // Show category breakdown + showCategoryBreakdown(categorizedTabs); + + // Generate roast + generateRoast(categorizedTabs, tabs.length); + }); + + chrome.storage.local.get(["ignoredDomains"], (data) => { + const ignored = data.ignoredDomains || {}; + const ignoredList = document.getElementById("ignored-list"); + ignoredList.innerHTML = ""; + + Object.keys(ignored).forEach((domain) => { + const listItem = document.createElement("div"); + + const checkbox = document.createElement("input"); + checkbox.type = "checkbox"; + checkbox.value = domain; + + listItem.appendChild(checkbox); + listItem.appendChild(document.createTextNode(domain)); + ignoredList.appendChild(listItem); + }); + + document.getElementById("toggle-ignored").addEventListener("click", () => { + toggleIgnoredDomains(); + }); + + const unignoreButton = document.createElement("button"); + unignoreButton.textContent = "Unignore selected domains"; + unignoreButton.style.marginTop = "10px"; + ignoredList.appendChild(unignoreButton); + unignoreButton.addEventListener("click", () => { + unignoreSelectedDomains(); + }); + }); + }); +} + +// Function to get domain from URL +function getDomain(url) { + try { + return new URL(url).hostname.replace("www.", "").split(".").slice(-2).join("."); // Normalize domain + } catch (e) { + return null; + } +} + +// Function to show the roast text +function showRoast(categorizedTabs, uncategorizedCount) { + let roastText = "Your tabs are categorized as:"; + for (let category in categorizedTabs) { + roastText += `
${category}: ${categorizedTabs[category].length} tab(s)`; + } + + if (uncategorizedCount > 0) roastText += `
Uncategorized tabs: ${uncategorizedCount}

`; + + document.getElementById("stats").innerHTML = roastText; +} + +// Function to display the tab count +function showTabCount(tabCount) { + document.getElementById("tab-count").textContent = `Total tabs open: ${tabCount}`; +} + +// Function to show the category breakdown +function showCategoryBreakdown(categorizedTabs) { + const breakdownListElement = document.getElementById("breakdown-list"); + const categoryBreakdownElement = document.getElementById("category-breakdown"); + + categoryBreakdownElement.addEventListener("click", () => { + breakdownListElement.style.display = breakdownListElement.style.display === "none" ? "block" : "none"; + }); + + let numEachDomain = {}; + + let categoryListHtml = ""; + for (let category in categorizedTabs) { + categorizedTabs[category].forEach((domain) => { + if (numEachDomain[domain]) numEachDomain[domain]++; + else numEachDomain[domain] = 1; + }); + + categoryListHtml += `
${category}
`; + Object.keys(numEachDomain).forEach(domain => { + categoryListHtml += `
${domain} (${numEachDomain[domain]})
`; + }); + + numEachDomain = {}; + } + + breakdownListElement.innerHTML = categoryListHtml; +} + +function loadCategories() { + chrome.storage.local.get(["categorizedDomains"], (data) => { + const categorized = data.categorizedDomains || {}; + const categoryList = document.getElementById("category-list"); + categoryList.innerHTML = ""; // Clear previous list + + const categories = []; + for (const [domain, category] of Object.entries(categorized)) { + if (!categories.includes(category)) { + categories.push(category); + } + } + + let activeButtonsContainer = null; + + categories.forEach(category => { + const categoryItem = document.createElement("div"); + categoryItem.classList.add("category-item"); + categoryItem.textContent = category; + categoryItem.style.textDecoration = "underline"; + categoryItem.style.textDecorationColor = "blue"; + categoryList.appendChild(categoryItem); + + // Buttons container + const buttonsContainer = document.createElement("div"); + buttonsContainer.style.display = "none"; + + // Edit Button + const editButton = document.createElement("button"); + editButton.textContent = "Edit"; + editButton.addEventListener("click", () => showEditCategoryUI(category)); + + // Delete Button + const deleteButton = document.createElement("button"); + deleteButton.textContent = "Delete"; + deleteButton.addEventListener("click", () => showDeleteCategoryUI(category)); + + buttonsContainer.appendChild(editButton); + buttonsContainer.appendChild(deleteButton); + categoryItem.appendChild(buttonsContainer); + + categoryItem.addEventListener("click", () => { + if (activeButtonsContainer && activeButtonsContainer !== buttonsContainer) { + activeButtonsContainer.style.display = "none"; + } + buttonsContainer.style.display = buttonsContainer.style.display === "none" ? "block" : "none"; + activeButtonsContainer = buttonsContainer.style.display === "block" ? buttonsContainer : null; + }); + + }); + }); +} + +function createFloatingModal(content) { + const modal = document.createElement("div"); + modal.classList.add("floating-modal"); + modal.innerHTML = ``; + document.body.appendChild(modal); + return modal; +} + +function showDeleteCategoryUI(category) { + const modal = createFloatingModal(` +

Are you sure you want to delete the category '${category}'? This will remove all associated domains.

+ + + `); + + document.getElementById("confirm-delete").addEventListener("click", () => { + deleteCategory(category); + modal.remove(); + }); + + document.getElementById("cancel-delete").addEventListener("click", () => { + modal.remove(); + }); +} + +function deleteCategory(category) { + chrome.storage.local.get(["categorizedDomains"], (data) => { + let categorized = data.categorizedDomains || {}; + + for (const domain in categorized) { + if (categorized[domain] === category) { + delete categorized[domain]; + } + } + + chrome.storage.local.set({ categorizedDomains: categorized }, () => { + loadCategories(); // Refresh UI + }); + }); +} + +function showEditCategoryUI(category, domains) { + const modal = createFloatingModal(` +

Enter a new name for the category '${category}':

+ + + + `); + + document.getElementById("confirm-edit").addEventListener("click", () => { + const newCategory = document.getElementById("new-category-name").value.trim(); + if (newCategory) { + editCategory(category, domains, newCategory); + modal.remove(); + } + }); + + document.getElementById("cancel-edit").addEventListener("click", () => { + modal.remove(); + }); +} + +function editCategory(category, domains, newCategory) { + chrome.storage.local.get(["categorizedDomains"], (data) => { + let categorized = data.categorizedDomains || {}; + + for (const domain of domains) { + categorized[domain] = newCategory; + } + + chrome.storage.local.set({ categorizedDomains: categorized }, () => { + loadCategories(); // Refresh UI + }); + }); +} + +function toggleIgnoredDomains() { + const ignoredList = document.getElementById("ignored-list"); + ignoredList.style.display = ignoredList.style.display === "none" ? "block" : "none"; +} + +function unignoreSelectedDomains() { + chrome.storage.local.get(["ignoredDomains"], (data) => { + const ignored = data.ignoredDomains || {}; + const ignoredList = document.getElementById("ignored-list"); + const checkboxes = ignoredList.querySelectorAll("input[type='checkbox']:checked"); + checkboxes.forEach((checkbox) => { + const domain = checkbox.value; + delete ignored[domain]; + }); + + chrome.storage.local.set({ ignoredDomains: ignored }, () => { + categorizeTabs(); + }); + }); +} + +function updateCurrentTabSection() { + chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { + if (tabs.length === 0) return; + const currentTab = tabs[0]; + const domain = getDomain(currentTab.url); + + if (detectSystemPage(currentTab.url)) { + document.getElementById("current-tab-category").textContent = "This is a system or extension page, which cannot be categorized"; + document.getElementById("current-tab-categorization-changes").style.display = "none"; + return; + } + + chrome.storage.local.get(["categorizedDomains"], (data) => { + const categorized = data.categorizedDomains || {}; + const category = categorized[domain] || "Uncategorized"; + document.getElementById("current-tab-category").textContent = category === "Uncategorized" ? `${capitalizeFirstLetter(domain)} is not categorized` : `${capitalizeFirstLetter(domain)} is categorized as ${category}`; + + // Populate the category dropdown + const categorySelect = document.getElementById("category-dropdown"); + categorySelect.innerHTML = ""; + + const uniqueCategories = new Set(Object.values(categorized)); + uniqueCategories.forEach((category) => { + const option = document.createElement("option"); + option.value = category; + option.textContent = category; + categorySelect.appendChild(option); + }); + }); + + document.getElementById("change-category").addEventListener("click", () => { + changeCurrentTabCategory(); + }); + document.getElementById("uncategorize-tab").addEventListener("click", () => { + uncategorizeCurrentTab(); + }); + }); +} + +function changeCurrentTabCategory() { + chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { + if (tabs.length === 0) return; + const currentTab = tabs[0]; + const domain = getDomain(currentTab.url); + const newCategory = document.getElementById("new-category-input").value.trim(); + const selectedCategory = document.getElementById("category-dropdown").value; + + const finalCategory = newCategory || selectedCategory; + + if (finalCategory) { + chrome.storage.local.get(["categorizedDomains"], (data) => { + let categorized = data.categorizedDomains || {}; + categorized[domain] = finalCategory; + + chrome.storage.local.set({ categorizedDomains: categorized }, () => { + updateCurrentTabSection(); // Refresh UI + }); + }); + } + }); +} + +function uncategorizeCurrentTab() { + chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { + if (tabs.length === 0) return; + const currentTab = tabs[0]; + const domain = getDomain(currentTab.url); + + chrome.storage.local.get(["categorizedDomains"], (data) => { + let categorized = data.categorizedDomains || {}; + if (categorized[domain]) { + delete categorized[domain]; + } + + chrome.storage.local.set({ categorizedDomains: categorized }, () => { + updateCurrentTabSection(); // Refresh UI + }); + }); + }); +} + +function generateRoast(categorizedTabs, numTabs) { + let roast = ""; + let categoryCounts = Object.entries(categorizedTabs).map(([category, domains]) => ({ category, count: domains.length })); + + if (categoryCounts.length === 0) return document.getElementById("roast").innerHTML = "Not one single categorized tab? How uncivilized."; + + categoryCounts.sort((a, b) => b.count - a.count); + let mostCommon = categoryCounts[0].category.toLowerCase().includes("misc") ? categoryCounts[1] : categoryCounts[0]; + + let finalistRoasts = []; + + if (!mostCommon) return document.getElementById("roast").innerHTML = "Not one single categorized tab? How uncivilized."; + + if (numTabs > 30) finalistRoasts.push(overThirtyTabs[Math.floor(Math.random() * overThirtyTabs.length)]); + else if (numTabs > 20) finalistRoasts.push(overTwentyTabs[Math.floor(Math.random() * overTwentyTabs.length)]); + + if (numTabs < 5) finalistRoasts.push(tooFewTabs[Math.floor(Math.random() * tooFewTabs.length)]); + + if (mostCommon.category.toLowerCase().includes("shop")) finalistRoasts.push(shoppingRoasts[Math.floor(Math.random() * shoppingRoasts.length)]); + else if (mostCommon.category.toLowerCase().includes("tertainment")) finalistRoasts.push(entertainmentRoasts[Math.floor(Math.random() * entertainmentRoasts.length)]); + else if (mostCommon.category.toLowerCase().includes("roductiv")) finalistRoasts.push(productivityRoasts[Math.floor(Math.random() * productivityRoasts.length)]); + else if (mostCommon.category.toLowerCase().includes("ocial")) finalistRoasts.push(socialRoasts[Math.floor(Math.random() * socialRoasts.length)]); + + let roastWinner = finalistRoasts.length > 0 ? finalistRoasts[Math.floor(Math.random() * finalistRoasts.length)] : "Congratulations! Somehow, I can't seem to find a way to roast you. You're either too organized or too chaotic. Either way, you win. (Try categorizing more tabs)"; + roast += roastWinner; + + document.getElementById("roast").innerHTML = roast; +} + + +document.addEventListener("DOMContentLoaded", () => { + // Floating modal style + document.head.appendChild(style); + + loadCategories(); + + // When the popup is opened, categorize tabs and show the UI + categorizeTabs(); + + updateCurrentTabSection(); +}); \ No newline at end of file From e903f3d083a80371360ba6a3934ba9dda984c14f Mon Sep 17 00:00:00 2001 From: theliendem Date: Mon, 17 Mar 2025 17:04:51 -0400 Subject: [PATCH 3/6] Create test --- submissions/Tabloid/icons/test | 1 + 1 file changed, 1 insertion(+) create mode 100644 submissions/Tabloid/icons/test diff --git a/submissions/Tabloid/icons/test b/submissions/Tabloid/icons/test new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/submissions/Tabloid/icons/test @@ -0,0 +1 @@ + From de7ee0ae58cb537b8cf9041a3364dc5deb8d488d Mon Sep 17 00:00:00 2001 From: theliendem Date: Mon, 17 Mar 2025 17:05:02 -0400 Subject: [PATCH 4/6] Add files via upload --- submissions/Tabloid/icons/icon128.jpg | Bin 0 -> 1243 bytes submissions/Tabloid/icons/icon16.jpg | Bin 0 -> 1038 bytes submissions/Tabloid/icons/icon48.jpg | Bin 0 -> 1979 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 submissions/Tabloid/icons/icon128.jpg create mode 100644 submissions/Tabloid/icons/icon16.jpg create mode 100644 submissions/Tabloid/icons/icon48.jpg diff --git a/submissions/Tabloid/icons/icon128.jpg b/submissions/Tabloid/icons/icon128.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7d6bd23b7d4270aaf16468c43af8916bbc0ede48 GIT binary patch literal 1243 zcmex=+ z$QDV5ur)yJBnaCE#4ax>C;_So0I`cgf}DZu6d+q89f_TU#7-_K0;%r-s5rZ)ISRxP=f? zS-`-+-@?GK?L0yZ5hewRMTubJSb!u`S{ehxr{xR`ypaqH!WS4AxT3*wKmv!`6o67P zKzHQ>VLC$&Ln?y;gC|2CLo$ONkY&VRz+lK=_Ww46GcYH3zSXkMZ**Q3Yk|Lm#iwZ!Z zf|#PW7;0uY@kNPk`-Wwo-kKdc zB|g9AH`l3HJz?#ZrPJ-$g1wiXa+rTUe9_xl(Rh2)XQxvu&z5H&%`Ue$pFKagdF7dB znTKV8rZIxd6kuol2Vyf6#6JMiAO?^Gvf(0_YOskw^+F5*agfXevK?f^e^60GQh&pK zxxI>?E?<&upLgNwvqR5MZ@1>w+*kWWMC)dGgm0M8tC*iZeXdOpXJTiKE8qHgYmLm6 zYMtEYysGPU*Q)$g%VXWfciVW`4jy3k0t0FBkFOtJUt+iPm-Bk#oA37A2(B!fofvI? zA+Bk5wBB^isfU72H`<5KI-B+U!1L7?%l37xpWoIm-MjeV?yZlu?rvOi$zkQeD=)WP Od6)*w8Q1~i|C<2hiuZc} literal 0 HcmV?d00001 diff --git a/submissions/Tabloid/icons/icon16.jpg b/submissions/Tabloid/icons/icon16.jpg new file mode 100644 index 0000000000000000000000000000000000000000..156a64e56ea03b199d24da85b9f0dd7b29c3ab17 GIT binary patch literal 1038 zcmex=+ z$QDV5ur)yJBnaCE#4ax>C;_So0I`cgf}DZu6d+q89f_TU#7-_K0;%r-s5rZ)ISRxP=f? zS-`-+-@?GK?L0yZ5hewRMTubJSb!u`S{ehxr{xR`ypaqH!WS4AxT3*wKmv!`6o67P zKzHQ>VLC$&Ln?y;gC|2CLo$ONkY&VRz+lK=_Ww46GcY)n3)(kfwCe<;!p)3 zQ9*=inCLAA9%e?MbeEM;ABuz63(xoWTTRjF+K>sGI_<>nWNe6-1# zKY90`mCdaAf6A-(Pf64G&rrR)YO?y}?E)7M7qXaSXvimcPPUP`X}bMIr2d6nUI*8& zyH#VR&+C8J>E1-Ip!G*PJ}O22mO9tA=CTprsQ`hu1=bt^dzJ@^?~yV;v@SdJ!@nu7 z8nXnqvQC-6I8E|PS^CA>$4X>mmz5}mwOrOPZ!Jx__%Fd_NaAW%JpKeM0-*@@XxVUG@M_w6o;U%52jo(-@E+77X695g) B5~WF_SRxwiMw5>j4EdOe(C+rZu8)#ZY@*GE zp^}}pw41akyG=+@*(LdCl_%TIMAm1qJF|E4>{I*f)Be-B&%NjOp7T5Bp8KAo>QME9 zu7|6;D_|G^h8C!vU>)u*F2O!rZ&!EE_0x_tLgdw!&$D_+pvHA$>3#aiyHRexaCpAvqA>M&F zK588A$8|wC4B>^sw=n-LED*=5`Pqo$6dRMMzDq6YifQ3-{=P_)(Kdzz;DQ@))bB^% zNJOOo4r2g>!*6W-LV)UY0E5mqw)w>XI%xox?!K|T`6uGg_|Vtsi0H&4A^?U@184^T z=-mULYLl-%0Y$6o zfKEn5u?QF)a5_eyV=5VX0N^-I_~)releGXNQ8YBE$ZMwyKq6uoQG<$2Q!t!J(jaIe z5}h)0mYM!+LnFt_wre+S4%oS`;LL-LIVehBJ=gyhwUz!~YbVeM7%GN9hc)o%rx!g_ zf{@tk&XJ&~i?eFJzw~s!Uw*88?%7fM%~O`_$J;7D_A9FlERlayx!%$)D)J1kw}ul& z)>{;KDxH#&d$2S6{#s9S^jrN|&EjC9uusr)L~# zD$lJj$w;~SVOVPvRYns0Fq%5n!*6gqc5HptiLJ)|i+D9&iOc0}EQaz{Prx3do!Hch zhG50lnjyk-4qKh7WeRCdlJ5c=4MulYs(eYMqgixRqr7F{?%87&CM!M}vfREZHM&e= z?AjVeVrtFHT>}RsP9=3sSG{x>3B@|>)m8FnJKMc>b|aDJ1|L`Lwd#KuoF|vwEWG-_ z#JauQQl{l^CC#RP(XHUSv%R~MKdqvin=rMqwB=V-^823H*Ru)CrFknH8g7Vsf>A0K zM|pd2&^3;+V4SLTm+tx{4hau6ZfiZe{Il5hjKuDFZf5{8*xA(7h-4(c!?3d6^mB zM&-1}y+K(Y4Xx`RDy*X_acsbC7iHO3qs=3kIadiP@V!p8j#4_aetp{BJ*1-~_5y?d zG9c#SFjhF%rkargNxVHIgJqM2uWmHjkj5nxL8QbnrPu;>KQ0BI*JFdapS_wOU*zl= zItj%eu$|T2Pl}aZo{hRsDvDu{%@QJmQ1>?qX5@$O&N$>z8h_?#M#{xT!P3YP*(=5m zwAB4QM)lSC!gW!+z;12@r)D|H&a!nOL)mT}u*bXrn`&$bejZ00zp(B0AB*dB9=Wbm zfk2FFe-+cUC7~zwxe=ArVXy0D@v|qh>E(%)CVEX%+VhTXFz2q)W(#v%1-AX43^yeI zPEcHt#m3xej%;(d;&9e8ow7|H-C7n>m&9vABdy_FXKq@^iu)W_k93$;)@n^O(zH!z zq;XS@v1WAg0O`W@_WIZek)3%~Utm|Z?Cf&;v|HRs!Q#}TLU9|{s?4`l>N%?5mR1Px# literal 0 HcmV?d00001 From a63998c4b4eb89a8c5edffe3549e9710ad3b0f9d Mon Sep 17 00:00:00 2001 From: theliendem Date: Wed, 19 Mar 2025 12:58:58 -0400 Subject: [PATCH 5/6] Add files via upload --- submissions/Tabloid/manifest.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/submissions/Tabloid/manifest.json b/submissions/Tabloid/manifest.json index 57792d3a..05aacca9 100644 --- a/submissions/Tabloid/manifest.json +++ b/submissions/Tabloid/manifest.json @@ -26,9 +26,9 @@ "service_worker": "background.js" }, "icons": { - "16": "icons/icon16.png", - "48": "icons/icon48.png", - "128": "icons/icon128.png" + "16": "icons/icon16.jpg", + "48": "icons/icon48.jpg", + "128": "icons/icon128.jpg" }, "browser_specific_settings": { "gecko": { From d9adc75743f11a4b237377d8ffddbff2819bf15d Mon Sep 17 00:00:00 2001 From: theliendem Date: Wed, 19 Mar 2025 13:00:09 -0400 Subject: [PATCH 6/6] Update manifest.json --- submissions/Tabloid/manifest.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/submissions/Tabloid/manifest.json b/submissions/Tabloid/manifest.json index 05aacca9..89149db9 100644 --- a/submissions/Tabloid/manifest.json +++ b/submissions/Tabloid/manifest.json @@ -17,9 +17,9 @@ "action": { "default_popup": "popup.html", "default_icon": { - "16": "icons/icon16.png", - "48": "icons/icon48.png", - "128": "icons/icon128.png" + "16": "icons/icon16.jpg", + "48": "icons/icon48.jpg", + "128": "icons/icon128.jpg" } }, "background": { @@ -35,4 +35,4 @@ "id": "tabuse@example.com" } } -} \ No newline at end of file +}