From a158a303b01416f81e69bb137b71d3369904b044 Mon Sep 17 00:00:00 2001 From: Daniel Dada Date: Tue, 7 Oct 2025 14:46:03 +0300 Subject: [PATCH] feat: add collapsible sections --- _locales/de/messages.json | 3 + _locales/en/messages.json | 3 + _locales/es/messages.json | 3 + _locales/fr/messages.json | 3 + _locales/hi/messages.json | 3 + _locales/it/messages.json | 3 + _locales/ja/messages.json | 3 + _locales/ko/messages.json | 3 + _locales/nl/messages.json | 3 + _locales/pl/messages.json | 3 + _locales/pt_BR/messages.json | 3 + _locales/ru/messages.json | 3 + _locales/tr/messages.json | 3 + _locales/zh_CN/messages.json | 3 + popup/popup.css | 56 +++++++++++++ popup/popup.html | 158 ++++++++++++++++++++++------------- popup/popup.js | 73 +++++++++++++++- 17 files changed, 268 insertions(+), 61 deletions(-) diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 3b79f29..5019080 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -115,5 +115,8 @@ }, "confirm_clear_exceptions": { "message": "Möchten Sie wirklich alle Ausnahmen löschen?" + }, + "remove": { + "message": "Entfernen" } } \ No newline at end of file diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 47f8694..5307f77 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "Are you sure you want to clear all exceptions?" + }, + "remove": { + "message": "Remove" } } \ No newline at end of file diff --git a/_locales/es/messages.json b/_locales/es/messages.json index e5202d7..7bcae99 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "¿Estás seguro de que deseas limpiar todas las excepciones?" + }, + "remove": { + "message": "Eliminar" } } \ No newline at end of file diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index 0dff166..656b2f6 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "Êtes-vous sûr de vouloir effacer toutes les exceptions ?" + }, + "remove": { + "message": "Supprimer" } } \ No newline at end of file diff --git a/_locales/hi/messages.json b/_locales/hi/messages.json index 0bc0da8..94c7f96 100644 --- a/_locales/hi/messages.json +++ b/_locales/hi/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "क्या आप वाकई सभी अपवादों को साफ करना चाहते हैं?" + }, + "remove": { + "message": "हटाएं" } } \ No newline at end of file diff --git a/_locales/it/messages.json b/_locales/it/messages.json index d6a7d13..0d44509 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "Sei sicuro di voler cancellare tutte le eccezioni?" + }, + "remove": { + "message": "Rimuovi" } } \ No newline at end of file diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json index 9b27a67..22b8a9a 100644 --- a/_locales/ja/messages.json +++ b/_locales/ja/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "すべての例外をクリアしてもよろしいですか?" + }, + "remove": { + "message": "削除" } } \ No newline at end of file diff --git a/_locales/ko/messages.json b/_locales/ko/messages.json index c5be855..254bb5a 100644 --- a/_locales/ko/messages.json +++ b/_locales/ko/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "모든 예외를 지우시겠습니까?" + }, + "remove": { + "message": "제거" } } \ No newline at end of file diff --git a/_locales/nl/messages.json b/_locales/nl/messages.json index 594334c..80d40e5 100644 --- a/_locales/nl/messages.json +++ b/_locales/nl/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "Weet je zeker dat je alle uitzonderingen wilt wissen?" + }, + "remove": { + "message": "Verwijderen" } } \ No newline at end of file diff --git a/_locales/pl/messages.json b/_locales/pl/messages.json index aaf9aee..dc9512f 100644 --- a/_locales/pl/messages.json +++ b/_locales/pl/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "Czy na pewno chcesz wyczyścić wszystkie wyjątki?" + }, + "remove": { + "message": "Usuń" } } \ No newline at end of file diff --git a/_locales/pt_BR/messages.json b/_locales/pt_BR/messages.json index a463bdf..40e2f6d 100644 --- a/_locales/pt_BR/messages.json +++ b/_locales/pt_BR/messages.json @@ -115,5 +115,8 @@ }, "confirm_clear_exceptions": { "message": "Tem certeza de que deseja limpar todas as exceções?" + }, + "remove": { + "message": "Remover" } } \ No newline at end of file diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index ca8bda2..4774017 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "Вы уверены, что хотите очистить все исключения?" + }, + "remove": { + "message": "Удалить" } } \ No newline at end of file diff --git a/_locales/tr/messages.json b/_locales/tr/messages.json index 3a7fdce..8a5fc69 100644 --- a/_locales/tr/messages.json +++ b/_locales/tr/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "Tüm istisnaları temizlemek istediğinizden emin misiniz?" + }, + "remove": { + "message": "Kaldır" } } \ No newline at end of file diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index 68f440d..77e1c94 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -121,5 +121,8 @@ }, "confirm_clear_exceptions": { "message": "您确定要清除所有例外吗?" + }, + "remove": { + "message": "移除" } } \ No newline at end of file diff --git a/popup/popup.css b/popup/popup.css index 912f013..8a2de53 100644 --- a/popup/popup.css +++ b/popup/popup.css @@ -80,6 +80,7 @@ h1 { border-radius: var(--border-radius); padding: 14px; box-shadow: var(--shadow); + transition: all 0.2s ease; } .section-header { @@ -87,6 +88,60 @@ h1 { justify-content: space-between; align-items: center; margin-bottom: 10px; + cursor: pointer; + padding-left: 8px; + padding-right: 8px; +} + +.section-header:hover { + background: var(--highlight-tag); + border-radius: 6px; + transition: background 0.2s ease; +} + +.collapse-toggle { + background: none !important; + border: none !important; + color: var(--text-color) !important; + padding: 4px !important; + margin: 0 !important; + cursor: pointer; + border-radius: 4px; + transition: all 0.2s ease; + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; +} + +.collapse-toggle:hover { + background: var(--button-hover) !important; + color: var(--accent) !important; +} + +.collapse-toggle i { + transition: transform 0.2s ease; + font-size: 0.8em; +} + +.section.collapsed .collapse-toggle i { + transform: rotate(180deg); +} + +.section-content { + overflow: hidden; + max-height: 2000px; +} + +.section.collapsed .section-content { + max-height: 0; + margin-bottom: 0; + padding-bottom: 0; +} + +.section.collapsed .section-header { + margin-bottom: 0; } .section h2 { @@ -96,6 +151,7 @@ h1 { display: flex; align-items: center; gap: 8px; + flex: 1; } input[type="text"], diff --git a/popup/popup.html b/popup/popup.html index 6785af6..6bc1bba 100644 --- a/popup/popup.html +++ b/popup/popup.html @@ -29,83 +29,121 @@ -
+

Site Exceptions

+
-
- - -
- -
+

Highlight Lists

+
- - -
- - -
-
- -
-

List Settings

- -
-
- Background: - -
-
- Foreground: - +
+ + +
+ +
-
-
-

Add Words

- - -
- -
-

Word List(0) -

-
- - - - - +
+
+

List Settings

+ +
+
+ +
+
+ Background: + +
+
+ Foreground: + +
+
+
- -
-
-

Options

-
- - +
+
+

Add Words

+
-
- - - +
+ + +
+
+ +
+
+

Word List(0) +

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

Options

+ +
+
+
+ + +
+
+ + + +
diff --git a/popup/popup.js b/popup/popup.js index 7e7cd46..14f1c1f 100644 --- a/popup/popup.js +++ b/popup/popup.js @@ -17,6 +17,51 @@ let matchCaseEnabled = false; let matchWholeEnabled = false; let exceptionsList = []; let currentTabHost = ''; +let sectionStates = {}; + +function loadSectionStates() { + const saved = localStorage.getItem('goose-highlighter-section-states'); + if (saved) { + try { + sectionStates = JSON.parse(saved); + } catch { + sectionStates = {}; + } + } +} + +function saveSectionStates() { + localStorage.setItem('goose-highlighter-section-states', JSON.stringify(sectionStates)); +} + +function toggleSection(sectionName) { + const section = document.querySelector(`[data-section="${sectionName}"]`); + if (!section) return; + + const isCollapsed = section.classList.contains('collapsed'); + + if (isCollapsed) { + section.classList.remove('collapsed'); + sectionStates[sectionName] = false; + } else { + section.classList.add('collapsed'); + sectionStates[sectionName] = true; + } + + saveSectionStates(); +} + +function initializeSectionStates() { + loadSectionStates(); + + // Apply saved states + Object.keys(sectionStates).forEach(sectionName => { + const section = document.querySelector(`[data-section="${sectionName}"]`); + if (section && sectionStates[sectionName]) { + section.classList.add('collapsed'); + } + }); +} function escapeHtml(str) { return str.replace(/[&<>"']/g, function (m) { @@ -278,13 +323,39 @@ function renderExceptions() { container.innerHTML = exceptionsList.map(domain => `
${escapeHtml(domain)} - +
` ).join(''); } document.addEventListener('DOMContentLoaded', () => { + initializeSectionStates(); localizePage(); + + // Add event listeners for collapse toggles + document.querySelectorAll('.collapse-toggle').forEach(button => { + button.addEventListener('click', (e) => { + e.stopPropagation(); + const targetSection = button.getAttribute('data-target'); + toggleSection(targetSection); + }); + }); + + // Also allow clicking section headers to toggle + document.querySelectorAll('.section-header').forEach(header => { + header.addEventListener('click', (e) => { + // Don't toggle if clicking on a button or input within the header + if (e.target.tagName === 'BUTTON' || e.target.tagName === 'INPUT' || e.target.closest('button')) { + return; + } + const section = header.closest('.section'); + const sectionName = section.getAttribute('data-section'); + if (sectionName) { + toggleSection(sectionName); + } + }); + }); + document.getElementById('selectAllBtn').onclick = () => { const list = lists[currentListIndex]; list.words.forEach((_, index) => {