diff --git a/img/logo-outlined-winter.png b/img/logo-outlined-winter.png new file mode 100644 index 0000000..91c087c Binary files /dev/null and b/img/logo-outlined-winter.png differ diff --git a/img/logo-winter.png b/img/logo-winter.png new file mode 100644 index 0000000..527d425 Binary files /dev/null and b/img/logo-winter.png differ diff --git a/popup/popup.css b/popup/popup.css index 33cf87d..1386f25 100644 --- a/popup/popup.css +++ b/popup/popup.css @@ -1,14 +1,14 @@ :root { - --bg-color: #0f0f0f; + --bg-color: #0d0f13; --text-color: #e8e8e8; - --input-bg: #1c1c1c; + --input-bg: #171b22; --input-border: #2d2d2d; --button-bg: #252525; --button-hover: #333333; --button-text: #e8e8e8; - --accent: #ec9c23; - --accent-hover: #ffb84d; - --accent-text: #000; + --accent: #7dc7ff; + --accent-hover: #a9ddff; + --accent-text: #000000; --highlight-tag: #222222; --highlight-tag-border: #3a3a3a; --danger: #ef4444; @@ -16,7 +16,7 @@ --shadow: 0 4px 12px rgba(0, 0, 0, 0.4); --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.3); --border-radius: 10px; - --section-bg: #161616; + --section-bg: #13161c; --switch-bg: #3a3a3a; --checkbox-accent: #ec9c23; --checkbox-border: #4a4a4a; @@ -73,22 +73,23 @@ body { } body.light { - --bg-color: #f8f9fa; + --bg-color: #eef6ff; --text-color: #1a1a1a; - --input-bg: #ffffff; - --input-border: #e0e0e0; - --button-bg: #f0f0f0; - --button-hover: #e5e5e5; + --input-bg: #f3f8ff; + --input-border: #d0e4ff; + --button-bg: #e0f0ff; + --button-hover: #cde8ff; --button-text: #1a1a1a; - --accent: #ec9c23; + --accent: #5ab6ff; --accent-text: #000; - --highlight-tag: #f5f5f5; - --highlight-tag-border: #e0e0e0; + --accent-hover: #8ccfff; + --highlight-tag: #d8edff; + --highlight-tag-border: #c0e0ff; --danger: #ef4444; --success: #10b981; --shadow: 0 4px 12px rgba(0, 0, 0, 0.08); --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.05); - --section-bg: #ffffff; + --section-bg: #f3f8ff; --switch-bg: #d1d5db; --checkbox-accent: #ec9c23; --checkbox-border: #9ca3af; @@ -872,3 +873,25 @@ body::-webkit-scrollbar-corner, opacity: 0.5; font-size: 0.85em; } + +.snow { + pointer-events: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + z-index: 1000; +} + +.snowflake { + position: absolute; + top: -10px; + color: #d0e7ff; + font-size: 6px; + opacity: 0.5; + user-select: none; + pointer-events: none; + will-change: transform; +} \ No newline at end of file diff --git a/popup/popup.html b/popup/popup.html index 4f03c3a..1cb1b70 100644 --- a/popup/popup.html +++ b/popup/popup.html @@ -11,6 +11,7 @@ +
@@ -18,7 +19,8 @@
- Goose Highlighter Goose Highlighter + Goose Highlighter Goose Highlighter
- - - - - + + + + +
@@ -68,7 +75,8 @@ Enable Highlighting - +
@@ -80,7 +88,8 @@
-

Word List (0)

+

Word List (0)

@@ -95,11 +104,13 @@
-

Highlights on This Page

+

Highlights on This Page +

Total: 0
- +
@@ -108,11 +119,13 @@

Site Exceptions

- +

Exception Sites:

- +
@@ -126,7 +139,8 @@
- +
diff --git a/src/popup/PopupController.ts b/src/popup/PopupController.ts index 1f3fee2..483d674 100644 --- a/src/popup/PopupController.ts +++ b/src/popup/PopupController.ts @@ -25,6 +25,7 @@ export class PopupController { this.setupEventListeners(); this.render(); this.hideLoadingOverlay(); + this.startSnow(); } private hideLoadingOverlay(): void { @@ -333,14 +334,14 @@ export class PopupController { document.getElementById('pageHighlightsList')?.addEventListener('click', async (e) => { const target = e.target as HTMLElement; const item = target.closest('.page-highlight-item') as HTMLElement; - + if (!item) return; const word = item.dataset.word; if (!word) return; const button = target.closest('button'); - + if (button?.classList.contains('highlight-prev')) { e.stopPropagation(); await this.navigateHighlight(word, -1); @@ -357,7 +358,7 @@ export class PopupController { private async loadPageHighlights(): Promise { try { const response = await MessageService.sendToActiveTab({ type: 'GET_PAGE_HIGHLIGHTS' }); - + if (response && response.highlights) { this.pageHighlights = response.highlights; this.highlightIndices.clear(); @@ -397,7 +398,7 @@ export class PopupController { private renderPageHighlights(): void { const container = document.getElementById('pageHighlightsList'); const countElement = document.getElementById('totalHighlightsCount'); - + if (!container || !countElement) return; const totalCount = this.pageHighlights.reduce((sum, h) => sum + h.count, 0); @@ -721,4 +722,86 @@ export class PopupController { (document.getElementById('matchCase') as HTMLInputElement).checked = this.matchCaseEnabled; (document.getElementById('matchWhole') as HTMLInputElement).checked = this.matchWholeEnabled; } + + // Ney year stuff + + private snowflakes: HTMLSpanElement[] = []; + +private startSnow(): void { + const maxFlakes = 20; + const spawnInterval = 500; + + const spawnFlake = () => { + if (this.snowflakes.length >= maxFlakes) return; + + const flake = document.createElement('div'); + flake.className = 'snowflake'; + flake.style.position = 'fixed'; + flake.style.pointerEvents = 'none'; + flake.style.zIndex = '9999'; + flake.style.fontSize = `${8 + Math.random() * 8}px`; + flake.textContent = '❄'; + + const isLightTheme = document.body.classList.contains('light'); + flake.style.color = isLightTheme ? 'rgba(90, 181, 255, 0.78)' : 'rgba(255, 255, 255, 0.8)'; + + flake.dataset.x = `${Math.random() * window.innerWidth}`; + flake.dataset.y = `${-10}`; + flake.dataset.speed = `${0.1 + Math.random() * 0.2}`; + flake.dataset.wind = `${Math.random() * 0.2 - 0.1}`; + flake.dataset.amplitude = `${1 + Math.random() * 1}`; + flake.dataset.angle = `${Math.random() * Math.PI * 2}`; + flake.dataset.angleSpeed = `${(Math.random() * 0.02 - 0.01)}`; + flake.dataset.opacity = `${0.2 + Math.random() * 0.3}`; + flake.style.opacity = flake.dataset.opacity!; + flake.dataset.fadeSpeed = `${0.002 + Math.random() * 0.003}`; + + document.body.appendChild(flake); + this.snowflakes.push(flake); + }; + + setInterval(spawnFlake, spawnInterval); + this.animateSnow(); +} + +private animateSnow(): void { + const animate = () => { + this.snowflakes.forEach((flake) => { + let x = parseFloat(flake.dataset.x!); + let y = parseFloat(flake.dataset.y!); + const speed = parseFloat(flake.dataset.speed!); + let wind = parseFloat(flake.dataset.wind!); + const amp = parseFloat(flake.dataset.amplitude!); + let angle = parseFloat(flake.dataset.angle!); + const angleSpeed = parseFloat(flake.dataset.angleSpeed!); + + y += speed; + angle += angleSpeed; + wind += (Math.random() * 0.002 - 0.001); + wind = Math.max(-0.1, Math.min(0.1, wind)); + x += Math.sin(angle) * amp + wind; + + if (y > window.innerHeight) { + y = -10; + x = Math.random() * window.innerWidth; + + if (Math.random() < 0.2) { + flake.remove(); + this.snowflakes = this.snowflakes.filter(f => f !== flake); + return; + } + } + + flake.dataset.x = `${x}`; + flake.dataset.y = `${y}`; + flake.dataset.angle = `${angle}`; + flake.dataset.wind = `${wind}`; + flake.style.transform = `translate(${x}px, ${y}px)`; + }); + + requestAnimationFrame(animate); + }; + + requestAnimationFrame(animate); +} } \ No newline at end of file