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