diff --git a/submissions/betterSummerHC/README.md b/submissions/betterSummerHC/README.md new file mode 100644 index 00000000..c714428f --- /dev/null +++ b/submissions/betterSummerHC/README.md @@ -0,0 +1,16 @@ +# betterSummerHC + +## Overview + +**betterSummerHC** is an extension that makes the Summer HackClub experience better with new features! + +--- + +## Features + +- **Hide Items** Hide all the items you don't want or have already buyed from the shop page. + +## Usage + +1. Open summer in a new page in the browser [https://summer.hackclub.com/](https://summer.hackclub.com/). +2. You will instantly see modified pages \ No newline at end of file diff --git a/submissions/betterSummerHC/assets/favicon.png b/submissions/betterSummerHC/assets/favicon.png new file mode 100644 index 00000000..4140552d Binary files /dev/null and b/submissions/betterSummerHC/assets/favicon.png differ diff --git a/submissions/betterSummerHC/assets/favicon128.png b/submissions/betterSummerHC/assets/favicon128.png new file mode 100644 index 00000000..09dcf259 Binary files /dev/null and b/submissions/betterSummerHC/assets/favicon128.png differ diff --git a/submissions/betterSummerHC/assets/favicon16.png b/submissions/betterSummerHC/assets/favicon16.png new file mode 100644 index 00000000..41789950 Binary files /dev/null and b/submissions/betterSummerHC/assets/favicon16.png differ diff --git a/submissions/betterSummerHC/assets/favicon48.png b/submissions/betterSummerHC/assets/favicon48.png new file mode 100644 index 00000000..291113e8 Binary files /dev/null and b/submissions/betterSummerHC/assets/favicon48.png differ diff --git a/submissions/betterSummerHC/manifest.json b/submissions/betterSummerHC/manifest.json new file mode 100644 index 00000000..ab9af1f2 --- /dev/null +++ b/submissions/betterSummerHC/manifest.json @@ -0,0 +1,48 @@ +{ + "manifest_version": 3, + "name": "betterSummerHC", + "version": "0.1.0", + "description": "An extension that makes the Summer HackClub experience better with new features!", + "permissions": [ + "activeTab", + "storage" + ], + "host_permissions": [ + "https://summer.hackclub.com/*" + ], + "action": { + "default_popup": "popup.html", + "default_icon": "assets/favicon128.png" + }, + "content_scripts": [ + { + "matches": [ + "https://summer.hackclub.com/*" + ], + "js": [ + "scripts/browser-polyfill.min.js", + "scripts/content.js", + "scripts/shop.js" + ] + }, + { + "matches": [ + "https://summer.hackclub.com/*" + ], + "js": [ + "scripts/firefoxfix.js" + ], + "world": "MAIN" + } + ], + "icons": { + "16": "assets/favicon16.png", + "48": "assets/favicon48.png", + "128": "assets/favicon128.png" + }, + "browser_specific_settings": { + "gecko": { + "id": "bettersummerhc@paoloo.it" + } + } +} \ No newline at end of file diff --git a/submissions/betterSummerHC/popup.html b/submissions/betterSummerHC/popup.html new file mode 100644 index 00000000..3ceb0cec --- /dev/null +++ b/submissions/betterSummerHC/popup.html @@ -0,0 +1,44 @@ + + + + + + + + + + +
+ + + +
+ +
+

General Settings

+ +
+ +
+
+ +
+ +
+ +
+

New Features

+

Stay tuned for more updates!

+
+ + + \ No newline at end of file diff --git a/submissions/betterSummerHC/popup.js b/submissions/betterSummerHC/popup.js new file mode 100644 index 00000000..04bfce34 --- /dev/null +++ b/submissions/betterSummerHC/popup.js @@ -0,0 +1,108 @@ +const tabsBtns = document.querySelectorAll('.tabs button'); + +function toggleTab(tabName) { + tabsBtns.forEach(btn => btn.classList.remove('active')); + document.querySelectorAll('.content').forEach(tab => tab.classList.remove('active')); + + const bt = document.querySelector(`button[data-tab="${tabName}"]`); + if (!bt) { + console.error(`Button for tab '${tabName}' not found.`); + return; + } + bt.classList.add('active'); + document.querySelector(`#${bt.dataset.tab}`).classList.add('active'); +} + +tabsBtns.forEach(bt => { + if (bt.dataset.url != undefined) { + const url = `https://summer.hackclub.com${bt.dataset.url}`; + + browser.tabs.query({ active: true, currentWindow: true }).then(tabs => { + const currentTab = tabs[0]; + if (currentTab.url === url) { + toggleTab(bt.dataset.tab); + } + }).catch(err => console.error('Error querying tabs:', err)); + } + + bt.addEventListener('click', () => { + if (bt.dataset.url != undefined) { + const url = `https://summer.hackclub.com${bt.dataset.url}`; + + browser.tabs.query({ active: true, currentWindow: true }).then(tabs => { + const currentTab = tabs[0]; + if (!(currentTab.url === url)) { + browser.tabs.update(currentTab.id, { url: url }); + } + }).catch(err => console.error('Error querying tabs:', err)); + } + toggleTab(bt.dataset.tab); + }); +}); + +(async () => { + const result = await browser.storage.sync.get(["shopHidden"]); + if (!result) { + browser.storage.sync.set({ shopHidden: [] }, () => { + console.warn("No hidden items found. Creating new list."); + }); + return; + } + + const shopHidden = result.shopHidden || []; + + const hideDiv = document.querySelector('.hidden > div'); + hideDiv.innerHTML = ''; + shopHidden.forEach(item => { + const itemElement = document.createElement('div'); + itemElement.textContent = item.split(".")[1].trim(); + + const unhideButton = document.createElement('button'); + unhideButton.textContent = 'Unhide'; + unhideButton.addEventListener('click', () => { + browser.storage.sync.get(["shopHidden"]).then(res => { + const updated = res.shopHidden.filter(i => i !== item); + browser.storage.sync.set({ shopHidden: updated }).then(() => { + itemElement.remove(); + }); + + browser.tabs.query({ active: true, currentWindow: true }).then(tabs => { + const activeTab = tabs[0]; + browser.tabs.sendMessage(activeTab.id, { action: 'unhide', id: item }) + .catch(err => console.warn('Content script may not be loaded in this tab:', err)); + }); + }); + }); + + itemElement.appendChild(unhideButton); + hideDiv.appendChild(itemElement); + }); + + document.querySelector('.hidden').style.display = shopHidden.length > 0 ? 'block' : 'none'; +})().catch(err => console.error('Error loading hidden items:', err)); + +// General +const infoButton = document.querySelector("input#hide-info"); + +if (infoButton) { + infoButton.addEventListener("change", async (e) => { + const hideInfoBanner = e.target.checked; + console.info("Setting hideInfoBanner to:", hideInfoBanner); + + await browser.storage.sync.set({ hideInfoBanner }); + console.info("hideInfoBanner updated in storage."); + + browser.tabs.query({ active: true, currentWindow: true }).then(tabs => { + const activeTab = tabs[0]; + browser.tabs.sendMessage(activeTab.id, { action: 'hideInfoBanner', force: hideInfoBanner }) + .catch(err => console.warn('Content script may not be loaded in this tab:', err)); + }); + }); + + (async () => { + const result = await browser.storage.sync.get(["hideInfoBanner"]); + console.log(result) + + infoButton.checked = result.hideInfoBanner || false; + })(); +} \ No newline at end of file diff --git a/submissions/betterSummerHC/popup/popup.css b/submissions/betterSummerHC/popup/popup.css new file mode 100644 index 00000000..e69de29b diff --git a/submissions/betterSummerHC/popup/popup.js b/submissions/betterSummerHC/popup/popup.js new file mode 100644 index 00000000..e69de29b diff --git a/submissions/betterSummerHC/scripts/browser-polyfill.min.js b/submissions/betterSummerHC/scripts/browser-polyfill.min.js new file mode 100644 index 00000000..0758a1e9 --- /dev/null +++ b/submissions/betterSummerHC/scripts/browser-polyfill.min.js @@ -0,0 +1,8 @@ +(function(a,b){if("function"==typeof define&&define.amd)define("webextension-polyfill",["module"],b);else if("undefined"!=typeof exports)b(module);else{var c={exports:{}};b(c),a.browser=c.exports}})("undefined"==typeof globalThis?"undefined"==typeof self?this:self:globalThis,function(a){"use strict";if(!(globalThis.chrome&&globalThis.chrome.runtime&&globalThis.chrome.runtime.id))throw new Error("This script should only be loaded in a browser extension.");if(!(globalThis.browser&&globalThis.browser.runtime&&globalThis.browser.runtime.id)){a.exports=(a=>{const b={alarms:{clear:{minArgs:0,maxArgs:1},clearAll:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getAll:{minArgs:0,maxArgs:0}},bookmarks:{create:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},getChildren:{minArgs:1,maxArgs:1},getRecent:{minArgs:1,maxArgs:1},getSubTree:{minArgs:1,maxArgs:1},getTree:{minArgs:0,maxArgs:0},move:{minArgs:2,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeTree:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}},browserAction:{disable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},enable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},getBadgeBackgroundColor:{minArgs:1,maxArgs:1},getBadgeText:{minArgs:1,maxArgs:1},getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},openPopup:{minArgs:0,maxArgs:0},setBadgeBackgroundColor:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setBadgeText:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},browsingData:{remove:{minArgs:2,maxArgs:2},removeCache:{minArgs:1,maxArgs:1},removeCookies:{minArgs:1,maxArgs:1},removeDownloads:{minArgs:1,maxArgs:1},removeFormData:{minArgs:1,maxArgs:1},removeHistory:{minArgs:1,maxArgs:1},removeLocalStorage:{minArgs:1,maxArgs:1},removePasswords:{minArgs:1,maxArgs:1},removePluginData:{minArgs:1,maxArgs:1},settings:{minArgs:0,maxArgs:0}},commands:{getAll:{minArgs:0,maxArgs:0}},contextMenus:{remove:{minArgs:1,maxArgs:1},removeAll:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},cookies:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:1,maxArgs:1},getAllCookieStores:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},devtools:{inspectedWindow:{eval:{minArgs:1,maxArgs:2,singleCallbackArg:!1}},panels:{create:{minArgs:3,maxArgs:3,singleCallbackArg:!0},elements:{createSidebarPane:{minArgs:1,maxArgs:1}}}},downloads:{cancel:{minArgs:1,maxArgs:1},download:{minArgs:1,maxArgs:1},erase:{minArgs:1,maxArgs:1},getFileIcon:{minArgs:1,maxArgs:2},open:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},pause:{minArgs:1,maxArgs:1},removeFile:{minArgs:1,maxArgs:1},resume:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},extension:{isAllowedFileSchemeAccess:{minArgs:0,maxArgs:0},isAllowedIncognitoAccess:{minArgs:0,maxArgs:0}},history:{addUrl:{minArgs:1,maxArgs:1},deleteAll:{minArgs:0,maxArgs:0},deleteRange:{minArgs:1,maxArgs:1},deleteUrl:{minArgs:1,maxArgs:1},getVisits:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1}},i18n:{detectLanguage:{minArgs:1,maxArgs:1},getAcceptLanguages:{minArgs:0,maxArgs:0}},identity:{launchWebAuthFlow:{minArgs:1,maxArgs:1}},idle:{queryState:{minArgs:1,maxArgs:1}},management:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},getSelf:{minArgs:0,maxArgs:0},setEnabled:{minArgs:2,maxArgs:2},uninstallSelf:{minArgs:0,maxArgs:1}},notifications:{clear:{minArgs:1,maxArgs:1},create:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:0},getPermissionLevel:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},pageAction:{getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},hide:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},permissions:{contains:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},request:{minArgs:1,maxArgs:1}},runtime:{getBackgroundPage:{minArgs:0,maxArgs:0},getPlatformInfo:{minArgs:0,maxArgs:0},openOptionsPage:{minArgs:0,maxArgs:0},requestUpdateCheck:{minArgs:0,maxArgs:0},sendMessage:{minArgs:1,maxArgs:3},sendNativeMessage:{minArgs:2,maxArgs:2},setUninstallURL:{minArgs:1,maxArgs:1}},sessions:{getDevices:{minArgs:0,maxArgs:1},getRecentlyClosed:{minArgs:0,maxArgs:1},restore:{minArgs:0,maxArgs:1}},storage:{local:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},managed:{get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1}},sync:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}}},tabs:{captureVisibleTab:{minArgs:0,maxArgs:2},create:{minArgs:1,maxArgs:1},detectLanguage:{minArgs:0,maxArgs:1},discard:{minArgs:0,maxArgs:1},duplicate:{minArgs:1,maxArgs:1},executeScript:{minArgs:1,maxArgs:2},get:{minArgs:1,maxArgs:1},getCurrent:{minArgs:0,maxArgs:0},getZoom:{minArgs:0,maxArgs:1},getZoomSettings:{minArgs:0,maxArgs:1},goBack:{minArgs:0,maxArgs:1},goForward:{minArgs:0,maxArgs:1},highlight:{minArgs:1,maxArgs:1},insertCSS:{minArgs:1,maxArgs:2},move:{minArgs:2,maxArgs:2},query:{minArgs:1,maxArgs:1},reload:{minArgs:0,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeCSS:{minArgs:1,maxArgs:2},sendMessage:{minArgs:2,maxArgs:3},setZoom:{minArgs:1,maxArgs:2},setZoomSettings:{minArgs:1,maxArgs:2},update:{minArgs:1,maxArgs:2}},topSites:{get:{minArgs:0,maxArgs:0}},webNavigation:{getAllFrames:{minArgs:1,maxArgs:1},getFrame:{minArgs:1,maxArgs:1}},webRequest:{handlerBehaviorChanged:{minArgs:0,maxArgs:0}},windows:{create:{minArgs:0,maxArgs:1},get:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:1},getCurrent:{minArgs:0,maxArgs:1},getLastFocused:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}}};if(0===Object.keys(b).length)throw new Error("api-metadata.json has not been included in browser-polyfill");class c extends WeakMap{constructor(a,b=void 0){super(b),this.createItem=a}get(a){return this.has(a)||this.set(a,this.createItem(a)),super.get(a)}}const d=a=>a&&"object"==typeof a&&"function"==typeof a.then,e=(b,c)=>(...d)=>{a.runtime.lastError?b.reject(new Error(a.runtime.lastError.message)):c.singleCallbackArg||1>=d.length&&!1!==c.singleCallbackArg?b.resolve(d[0]):b.resolve(d)},f=a=>1==a?"argument":"arguments",g=(a,b)=>function(c,...d){if(d.lengthb.maxArgs)throw new Error(`Expected at most ${b.maxArgs} ${f(b.maxArgs)} for ${a}(), got ${d.length}`);return new Promise((f,g)=>{if(b.fallbackToNoCallback)try{c[a](...d,e({resolve:f,reject:g},b))}catch(e){console.warn(`${a} API method doesn't seem to support the callback parameter, `+"falling back to call it without a callback: ",e),c[a](...d),b.fallbackToNoCallback=!1,b.noCallback=!0,f()}else b.noCallback?(c[a](...d),f()):c[a](...d,e({resolve:f,reject:g},b))})},h=(a,b,c)=>new Proxy(b,{apply(b,d,e){return c.call(d,a,...e)}});let i=Function.call.bind(Object.prototype.hasOwnProperty);const j=(a,b={},c={})=>{let d=Object.create(null),e=Object.create(a);return new Proxy(e,{has(b,c){return c in a||c in d},get(e,f){if(f in d)return d[f];if(!(f in a))return;let k=a[f];if("function"==typeof k){if("function"==typeof b[f])k=h(a,a[f],b[f]);else if(i(c,f)){let b=g(f,c[f]);k=h(a,a[f],b)}else k=k.bind(a);}else if("object"==typeof k&&null!==k&&(i(b,f)||i(c,f)))k=j(k,b[f],c[f]);else if(i(c,"*"))k=j(k,b[f],c["*"]);else return Object.defineProperty(d,f,{configurable:!0,enumerable:!0,get(){return a[f]},set(b){a[f]=b}}),k;return d[f]=k,k},set(b,c,e){return c in d?d[c]=e:a[c]=e,!0},defineProperty(a,b,c){return Reflect.defineProperty(d,b,c)},deleteProperty(a,b){return Reflect.deleteProperty(d,b)}})},k=a=>({addListener(b,c,...d){b.addListener(a.get(c),...d)},hasListener(b,c){return b.hasListener(a.get(c))},removeListener(b,c){b.removeListener(a.get(c))}}),l=new c(a=>"function"==typeof a?function(b){const c=j(b,{},{getContent:{minArgs:0,maxArgs:0}});a(c)}:a),m=new c(a=>"function"==typeof a?function(b,c,e){let f,g,h=!1,i=new Promise(a=>{f=function(b){h=!0,a(b)}});try{g=a(b,c,f)}catch(a){g=Promise.reject(a)}const j=!0!==g&&d(g);if(!0!==g&&!j&&!h)return!1;const k=a=>{a.then(a=>{e(a)},a=>{let b;b=a&&(a instanceof Error||"string"==typeof a.message)?a.message:"An unexpected error occurred",e({__mozWebExtensionPolyfillReject__:!0,message:b})}).catch(a=>{console.error("Failed to send onMessage rejected reply",a)})};return j?k(g):k(i),!0}:a),n=({reject:b,resolve:c},d)=>{a.runtime.lastError?a.runtime.lastError.message==="The message port closed before a response was received."?c():b(new Error(a.runtime.lastError.message)):d&&d.__mozWebExtensionPolyfillReject__?b(new Error(d.message)):c(d)},o=(a,b,c,...d)=>{if(d.lengthb.maxArgs)throw new Error(`Expected at most ${b.maxArgs} ${f(b.maxArgs)} for ${a}(), got ${d.length}`);return new Promise((a,b)=>{const e=n.bind(null,{resolve:a,reject:b});d.push(e),c.sendMessage(...d)})},p={devtools:{network:{onRequestFinished:k(l)}},runtime:{onMessage:k(m),onMessageExternal:k(m),sendMessage:o.bind(null,"sendMessage",{minArgs:1,maxArgs:3})},tabs:{sendMessage:o.bind(null,"sendMessage",{minArgs:2,maxArgs:3})}},q={clear:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}};return b.privacy={network:{"*":q},services:{"*":q},websites:{"*":q}},j(a,p,b)})(chrome)}else a.exports=globalThis.browser}); +//# sourceMappingURL=browser-polyfill.min.js.map + +// webextension-polyfill v.0.12.0 (https://github.com/mozilla/webextension-polyfill) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/submissions/betterSummerHC/scripts/content.js b/submissions/betterSummerHC/scripts/content.js new file mode 100644 index 00000000..66c53766 --- /dev/null +++ b/submissions/betterSummerHC/scripts/content.js @@ -0,0 +1,29 @@ +// Pulsante Info +async function hideInfoBanner(force = false) { + const result = await browser.storage.sync.get(["hideInfoBanner"]); + console.info("Hide Info Banner result:", result); + + const infoBanner = document.querySelector('.tutorial-help-btn'); + + if (!force && !result.hideInfoBanner) { + if (infoBanner) { + infoBanner.style.display = 'block'; + } + console.info("Info Banner not hidden as per user preference."); + return; + } + + if (infoBanner) { + infoBanner.style.display = 'none'; + } +} +hideInfoBanner(); + +window.addEventListener("custom:navigation", (e) => { + hideInfoBanner(); +}); +browser.runtime.onMessage.addListener((message) => { + if (message.action === 'hideInfoBanner') { + hideInfoBanner(message.force); + } +}); \ No newline at end of file diff --git a/submissions/betterSummerHC/scripts/firefoxfix.js b/submissions/betterSummerHC/scripts/firefoxfix.js new file mode 100644 index 00000000..c62f59cd --- /dev/null +++ b/submissions/betterSummerHC/scripts/firefoxfix.js @@ -0,0 +1,22 @@ +(function() { + const origPush = history.pushState; + const origReplace = history.replaceState; + + function fireEvent() { + window.dispatchEvent(new CustomEvent("custom:navigation", { + detail: { url: location.href } + })); + } + + history.pushState = function(...args) { + origPush.apply(this, args); + fireEvent(); + }; + + history.replaceState = function(...args) { + origReplace.apply(this, args); + fireEvent(); + }; + + window.addEventListener("popstate", fireEvent); +})(); diff --git a/submissions/betterSummerHC/scripts/shop.js b/submissions/betterSummerHC/scripts/shop.js new file mode 100644 index 00000000..2052eedb --- /dev/null +++ b/submissions/betterSummerHC/scripts/shop.js @@ -0,0 +1,120 @@ +function getID(card, index) { + return index + ". " + card.querySelector(".flex-grow h3.font-bold").textContent.trim(); +} + +function listenerFn(message) { + if (message.action === 'unhide') { + const id = message.id.split(".")[0].trim(); + const item = Array.from(cards)[id]; + + if (!item) return; + + item.style.display = 'block'; + browser.storage.sync.get(["shopHidden"]).then(res => { + const updated = res.shopHidden.filter(i => i !== id); + browser.storage.sync.set({ shopHidden: updated }) + }); + } +} + +const shopFn = async (loc = window.location) => { + if (!(loc.url || loc.href).includes("shop")) + return; + + // made with AI because it's too hard. sorry :( + await ( + new Promise(resolve => { + const checkExist = setInterval(() => { + if (document.querySelector('.card-with-gradient[data-padding="md"]')) { + clearInterval(checkExist); + resolve(); + } + }, 100); + }) + ) + + const cards = document.querySelectorAll('.my-6 .flex.flex-col .card-with-gradient[data-padding="md"]'); + + cards.forEach((card, index) => { + const ID = getID(card, index); + const btn = document.createElement('button'); + btn.textContent = 'Hide'; + + btn.style.position = 'absolute'; + btn.style.top = '20px'; + btn.style.left = '15px'; + btn.style.backgroundColor = 'rgba(224, 73, 27, 0.8)'; + btn.style.border = '1px solid #ccc'; + btn.style.borderRadius = '24px'; + btn.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.1)'; + btn.style.color = '#FFF'; + + + btn.style.zIndex = '1000'; + btn.style.padding = '4px 8px'; + btn.style.fontSize = '12px'; + btn.style.cursor = 'pointer'; + + card.style.position = card.style.position || 'relative'; + + btn.addEventListener('click', async () => { + const res = await browser.storage.sync.get(["shopHidden"]); + + if (!res) { + browser.storage.sync.set({ shopHidden: [ID] }, () => { + item.style.display = "none"; + }); + + return; + } + + const shopHidden = res.shopHidden || []; + + if (!shopHidden.includes(ID)) { + shopHidden.push(ID); + + await browser.storage.sync.set({ shopHidden }); + card.style.display = "none"; + } + }); + + card.appendChild(btn); + }); + + const result = await browser.storage.sync.get(["shopHidden"]); + if (!result) { + browser.storage.sync.set({ shopHidden: [] }, () => {}); + } + + const shopHidden = result.shopHidden || []; + + cards.forEach((item, index) => { + const ID = getID(item, index); + + if (shopHidden.includes(ID)) { + item.style.display = "none"; + } + }); + console.info("Hide buttons set up for shop items."); + console.info("Shop items hidden based on stored preferences."); + + try { + browser.runtime.onMessage.removeListener(listenerFn); + } catch (e) { } + browser.runtime.onMessage.addListener(listenerFn); +}; + +/** + * Me del futuro: questo controlla se l'url รจ cambiato e esegue il codice + * https://stackoverflow.com/a/52809105 + */ +// window.navigation.addEventListener("navigate", (event) => { +// shopFn(event.destination); +// }); +// FIx for firefox from chatgpt +window.addEventListener("custom:navigation", (e) => { + shopFn(new URL(e.detail.url)); +}); +shopFn(); + + diff --git a/submissions/betterSummerHC/styles/popup.css b/submissions/betterSummerHC/styles/popup.css new file mode 100644 index 00000000..2acbe260 --- /dev/null +++ b/submissions/betterSummerHC/styles/popup.css @@ -0,0 +1,184 @@ +body { + font-family: Arial, sans-serif; + width: 300px; + padding: 10px; + + --main-c: #4a2d24; + --main-c-light: #d0b194; + --main-c-dark: #ca8862dc; + --main-c-text: #ffffff; + --main-c-text-light: #f0f0f0; + --main-c-text-dark: #000000; + + --background: #f1d9bb; + --background-text: #423838; + + background-color: var(--background); + color: var(--background-text); +} + +.tabs { + display: flex; + margin-bottom: 10px; +} + +.tabs>button { + flex: 1; + padding: 8px; + border: none; + background-color: var(--main-c-light); + cursor: pointer; + + transition: all .4s; + + &:first-of-type { + border-top-left-radius: 16px; + border-bottom-left-radius: 16px; + } + + &:last-of-type { + border-top-right-radius: 16px; + border-bottom-right-radius: 16px; + } + + &:hover { + background-color: var(--main-c-dark); + color: white; + } + + &.active { + background-color: var(--main-c); + color: white; + } +} + +div.title { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + + text-align: center; +} + +div.title>button { + padding: 4px 12px; + background-color: var(--main-c); + color: white; + border: none; + border-radius: 12px; + cursor: pointer; + + &:hover { + background-color: var(--main-c-dark); + transition: all .4s; + } +} + +.content { + display: none; + + &.active { + display: block; + } +} + +#general>.settings { + display: flex; + flex-direction: column; + gap: 8px; + + &>label { + display: flex; + flex-direction: column; + justify-content: space-between; + gap: 4px; + + padding: 10px 8px; + background-color: var(--main-c-dark); + color: var(--main-c-text-light); + border-radius: 12px; + + &.checkbox { + flex-direction: row; + align-items: center; + cursor: pointer; + + &>input { + all: unset; + width: 20px; + height: 20px; + border-radius: 4px; + background-color: var(--main-c-light); + border: 1px solid var(--main-c); + cursor: pointer; + position: relative; + transition: all .4s; + + &:checked { + background-color: var(--main-c); + } + &:checked::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 10px; + height: 10px; + background-color: var(--main-c-text); + border-radius: 2px; + } + &:hover { + background-color: var(--main-c-dark); + transition: all .4s; + } + } + } + + &>input { + padding: 4px; + border-radius: 8px; + border: 1px solid var(--main-c-light); + background-color: var(--main-c-light); + color: var(--main-c-text-dark); + } + } +} + +#shop>.hidden { + display: none; + + &>div { + overflow-y: auto; + max-height: 300px; + + display: flex; + flex-direction: column; + gap: 4px; + + &>div { + display: flex; + align-items: center; + justify-content: space-between; + padding: 4px; + background-color: var(--main-c-light); + border-radius: 8px; + + & > button { + padding: 2px 8px; + background-color: var(--main-c); + color: var(--main-c-text); + border: none; + border-radius: 8px; + cursor: pointer; + font-size: .8rem; + + &:hover { + background-color: var(--main-c-dark); + transition: all .4s; + } + } + } + } +} \ No newline at end of file