diff --git a/plugins/colorama-lyrics-luna/src/Settings.tsx b/plugins/colorama-lyrics-luna/src/Settings.tsx index c46521d..f70a1de 100644 --- a/plugins/colorama-lyrics-luna/src/Settings.tsx +++ b/plugins/colorama-lyrics-luna/src/Settings.tsx @@ -2,6 +2,12 @@ import { ReactiveStore } from "@luna/core"; import { LunaSettings, LunaSwitchSetting } from "@luna/ui"; import React from "react"; +declare global { + interface Window { + applyColoramaLyrics?: () => void; + } +} + export type ColoramaMode = | "single" | "gradient-experimental" @@ -24,7 +30,7 @@ export const settings = await ReactiveStore.getPluginStorage("ColoramaLyrics", { }); export const Settings = () => { - const [enabled, setEnabled] = React.useState(settings.enabled); + // const [enabled, setEnabled] = React.useState(settings.enabled); const [mode, setMode] = React.useState(settings.mode); const [singleColor, setSingleColor] = React.useState(settings.singleColor); const [singleAlpha, setSingleAlpha] = React.useState( @@ -54,7 +60,9 @@ export const Settings = () => { const [activeEndpoint, setActiveEndpoint] = React.useState< "single" | "start" | "end" >("single"); - const AnySwitch = LunaSwitchSetting as unknown as React.ComponentType; + const AnySwitch = LunaSwitchSetting as unknown as React.ComponentType< + Record + >; // Helper for HEX normalization const normalizeToRGB = ( @@ -125,14 +133,17 @@ export const Settings = () => { if (!hexColorRegex.test(trimmed)) return; if (mode === "single") { const next = normalizeToRGB(trimmed); - setSingleColor((settings.singleColor = next)); + settings.singleColor = next; + setSingleColor(next); if (updateInput) setCustomInput(next); } else if (mode === "gradient-experimental") { const norm = normalizeToRGB(trimmed); if (activeEndpoint === "end") { - setGradientEnd((settings.gradientEnd = norm)); + settings.gradientEnd = norm; + setGradientEnd(norm); } else { - setGradientStart((settings.gradientStart = norm)); + settings.gradientStart = norm; + setGradientStart(norm); } if (updateInput) setCustomInput(norm); } @@ -152,16 +163,16 @@ export const Settings = () => { } }; - const removeCustomColor = (color: string) => { - const updated = customColors.filter((c) => c !== color); - setCustomColors(updated); - settings.customColors = updated; - }; + // const removeCustomColor = (color: string) => { + // const updated = customColors.filter((c) => c !== color); + // setCustomColors(updated); + // settings.customColors = updated; + // }; const allColors = [...colorPresets, ...customColors]; const requestApply = () => { - (window as any).applyColoramaLyrics?.(); + window.applyColoramaLyrics?.(); }; return ( @@ -185,7 +196,8 @@ export const Settings = () => { value={mode} onChange={(e) => { const next = e.target.value as ColoramaMode; - setMode((settings.mode = next)); + settings.mode = next; + setMode(next); requestApply(); }} style={{ @@ -250,6 +262,7 @@ export const Settings = () => { }} > @@ -586,7 +610,8 @@ export const Settings = () => { value={singleAlpha} onChange={(e) => { const value = Number(e.target.value); - setSingleAlpha((settings.singleAlpha = value)); + settings.singleAlpha = value; + setSingleAlpha(value); requestApply(); }} style={{ width: "100%" }} @@ -628,9 +653,8 @@ export const Settings = () => { value={gradientStartAlpha} onChange={(e) => { const value = Number(e.target.value); - setGradientStartAlpha( - (settings.gradientStartAlpha = value), - ); + settings.gradientStartAlpha = value; + setGradientStartAlpha(value); requestApply(); }} style={{ width: "100%" }} @@ -668,7 +692,8 @@ export const Settings = () => { value={gradientEndAlpha} onChange={(e) => { const value = Number(e.target.value); - setGradientEndAlpha((settings.gradientEndAlpha = value)); + settings.gradientEndAlpha = value; + setGradientEndAlpha(value); requestApply(); }} style={{ width: "100%" }} @@ -702,7 +727,8 @@ export const Settings = () => { value={gradientAngle} onChange={(e) => { const value = Number(e.target.value); - setGradientAngle((settings.gradientAngle = value)); + settings.gradientAngle = value; + setGradientAngle(value); requestApply(); }} style={{ width: "100%" }} @@ -736,7 +762,8 @@ export const Settings = () => { value={gradientAngle} onChange={(e) => { const value = Number(e.target.value); - setGradientAngle((settings.gradientAngle = value)); + settings.gradientAngle = value; + setGradientAngle(value); requestApply(); }} style={{ width: "100%" }} @@ -756,6 +783,7 @@ export const Settings = () => { cursor: "pointer", fontSize: 12, }} + type="button" > Done @@ -767,7 +795,8 @@ export const Settings = () => { desc="Apply color/gradient only to the currently active lyric line" checked={excludeInactive} onChange={(_: unknown, checked: boolean) => { - setExcludeInactive((settings.excludeInactive = checked)); + settings.excludeInactive = checked; + setExcludeInactive(checked); requestApply(); }} /> diff --git a/plugins/copy-lyrics-luna/src/index.ts b/plugins/copy-lyrics-luna/src/index.ts index f03d40e..04c7e52 100644 --- a/plugins/copy-lyrics-luna/src/index.ts +++ b/plugins/copy-lyrics-luna/src/index.ts @@ -1,4 +1,4 @@ -import { LunaUnload, Tracer } from "@luna/core"; +import { type LunaUnload, Tracer } from "@luna/core"; import { StyleTag } from "@luna/lib"; // Import CSS directly using Luna's file:// syntax - Took me a while to figure out <3 @@ -9,8 +9,8 @@ export const { trace } = Tracer("[Copy Lyrics]"); // clean up resources export const unloads = new Set(); -// StyleTag for lyrics selection styling -const lyricsStyleTag = new StyleTag("Copy-Lyrics", unloads, unlockSelection); +// Style injection via side effect +new StyleTag("Copy-Lyrics", unloads, unlockSelection); function SetClipboard(text: string): void { const textarea = document.createElement("textarea"); @@ -31,17 +31,17 @@ function SetClipboard(text: string): void { let isSelecting = false; -const onMouseDown = function (): void { +const onMouseDown = (): void => { isSelecting = true; }; -const onMouseUp = function (event: MouseEvent): void { +const onMouseUp = (): void => { if (isSelecting) { const selection = window.getSelection(); - if (selection && selection.toString().length > 0) { + if (selection?.toString().length > 0) { const selectedSpans: HTMLSpanElement[] = []; const range = selection.getRangeAt(0); - let container = range.commonAncestorContainer; + const container = range.commonAncestorContainer; // If the container is NOT an element and a document, adjust it. if ( @@ -50,8 +50,8 @@ const onMouseUp = function (event: MouseEvent): void { ) { // Get the parent element if it's a text node const parentElement = container.parentElement; - if (parentElement && parentElement.hasAttribute("data-current")) { - let text_ = selection.toString().trim(); + if (parentElement?.hasAttribute("data-current")) { + const text_ = selection.toString().trim(); SetClipboard(text_); trace.msg.log("Copied to clipboard!"); return; @@ -60,7 +60,7 @@ const onMouseUp = function (event: MouseEvent): void { // Get all the spans inside the container. const spans = (container as Element).getElementsByTagName("span"); - for (let span of spans) { + for (const span of spans) { if (selection.containsNode(span, true)) { selectedSpans.push(span as HTMLSpanElement); } @@ -95,7 +95,7 @@ const onMouseUp = function (event: MouseEvent): void { } }; -const onClickHooked = function (event: MouseEvent): boolean | void { +const onClickHooked = (event: MouseEvent): boolean | undefined => { if (!isSelecting) return; const target = event.target as HTMLElement; @@ -109,15 +109,19 @@ const onClickHooked = function (event: MouseEvent): boolean | void { event.stopImmediatePropagation(); return false; } + return undefined; }; // Add event listener with capture phase to intercept events before they reach other handlers + document.addEventListener("click", onClickHooked, true); + document.addEventListener("mousedown", onMouseDown); + document.addEventListener("mouseup", onMouseUp); // Add cleanup to unloads -unloads.add(() => { +unloads.add((): void => { // Remove event listeners document.removeEventListener("click", onClickHooked, true); document.removeEventListener("mousedown", onMouseDown); diff --git a/plugins/element-hider-luna/src/index.ts b/plugins/element-hider-luna/src/index.ts index 98252be..d20bff4 100644 --- a/plugins/element-hider-luna/src/index.ts +++ b/plugins/element-hider-luna/src/index.ts @@ -1,5 +1,5 @@ -import { LunaUnload, Tracer } from "@luna/core"; -import { StyleTag, ContextMenu } from "@luna/lib"; +import { type LunaUnload, Tracer } from "@luna/core"; +import { StyleTag } from "@luna/lib"; import { settings, Settings } from "./Settings"; // Import CSS directly using Luna's file:// syntax @@ -13,8 +13,8 @@ export { Settings }; // Clean up resources export const unloads = new Set(); -// StyleTag for element hider -const styleTag = new StyleTag("Element-Hider", unloads, styles); +// StyleTag for element hider (side-effect) +new StyleTag("Element-Hider", unloads, styles); // State management let targetElement: HTMLElement | null = null; @@ -144,19 +144,18 @@ function saveHiddenElement(element: HTMLElement): void { } } -// Remove hidden element from persistent storage (for unhiding) -function removeSavedElement(element: HTMLElement): void { - const selector = generateElementSelector(element); - const index = settings.hiddenElements.findIndex( - (stored) => stored.selector === selector, - ); - - if (index !== -1) { - settings.hiddenElements.splice(index, 1); - trace.log(`Permanently removed: ${selector}`); - trace.log(`Remaining stored: ${settings.hiddenElements.length}`); - } -} +// Remove hidden element from persistent storage (for unhiding) - currently unused +// function removeSavedElement(element: HTMLElement): void { +// const selector = generateElementSelector(element); +// const index = settings.hiddenElements.findIndex( +// (stored) => stored.selector === selector, +// ); +// if (index !== -1) { +// settings.hiddenElements.splice(index, 1); +// trace.log(`Permanently removed: ${selector}`); +// trace.log(`Remaining stored: ${settings.hiddenElements.length}`); +// } +// } // Check if an element matches any stored selector (EXACT match only) function matchesStoredSelector(element: HTMLElement): boolean { @@ -324,8 +323,15 @@ function setupElementObserver(): void { } // Global functions -(window as any).showAllElementsFromSettings = unhideAllElements; -(window as any).debugElementHider = () => { +declare global { + interface Window { + showAllElementsFromSettings?: () => void; + debugElementHider?: () => void; + } +} + +window.showAllElementsFromSettings = unhideAllElements; +window.debugElementHider = () => { trace.log(`=== Element Hider Debug Info ===`); trace.log(`Stored elements: ${settings.hiddenElements.length}`); trace.log(`Currently hidden elements: ${hiddenElementsArray.length}`); @@ -662,8 +668,8 @@ unloads.add(() => { removeHighlight(); // Clean up global functions - (window as any).showAllElementsFromSettings = undefined; - (window as any).debugElementHider = undefined; + window.showAllElementsFromSettings = undefined; + window.debugElementHider = undefined; trace.log("Plugin unloaded"); }); diff --git a/plugins/oled-theme-luna/src/index.ts b/plugins/oled-theme-luna/src/index.ts index 9c47707..fb8cdfa 100644 --- a/plugins/oled-theme-luna/src/index.ts +++ b/plugins/oled-theme-luna/src/index.ts @@ -1,11 +1,5 @@ -import { LunaUnload, Tracer } from "@luna/core"; -import { - StyleTag, - observePromise, - PlayState, - Quality, - type MediaItem, -} from "@luna/lib"; +import { type LunaUnload, Tracer } from "@luna/core"; +import { StyleTag, observePromise, PlayState } from "@luna/lib"; import { settings, Settings } from "./Settings"; // Import CSS files directly using Luna's file:// syntax - Took me a while to figure out <3 @@ -109,7 +103,7 @@ const setupQualityMonitoring = (): void => { }; // Function to apply theme styles based on current settings -const applyThemeStyles = function (): void { +const applyThemeStyles = (): void => { // Choose the appropriate CSS file based on settings let selectedStyle: string; @@ -141,7 +135,13 @@ const applyThemeStyles = function (): void { }; // Make this function available globally so Settings can call it -(window as any).updateOLEDThemeStyles = applyThemeStyles; +declare global { + interface Window { + updateOLEDThemeStyles?: () => void; + } +} + +window.updateOLEDThemeStyles = applyThemeStyles; // Apply the OLED theme initially applyThemeStyles(); diff --git a/plugins/radiant-lyrics-luna/src/Settings.tsx b/plugins/radiant-lyrics-luna/src/Settings.tsx index ef17605..d5ef020 100644 --- a/plugins/radiant-lyrics-luna/src/Settings.tsx +++ b/plugins/radiant-lyrics-luna/src/Settings.tsx @@ -54,13 +54,18 @@ export const Settings = () => { settings.trackTitleGlow, ); + // Use a permissive wrapper to align with current usage props + const AnySwitch = LunaSwitchSetting as unknown as React.ComponentType< + Record + >; + return ( - { + onChange={(_event: unknown, checked: boolean) => { setLyricsGlowEnabled((settings.lyricsGlowEnabled = checked)); // Update styles immediately when setting changes if ((window as any).updateRadiantLyricsStyles) { @@ -68,30 +73,30 @@ export const Settings = () => { } }} /> - { + onChange={(_event: unknown, checked: boolean) => { setTrackTitleGlow((settings.trackTitleGlow = checked)); if ((window as any).updateRadiantLyricsStyles) { (window as any).updateRadiantLyricsStyles(); } }} /> - { + onChange={(_event: unknown, checked: boolean) => { setHideUIEnabled((settings.hideUIEnabled = checked)); }} /> - { + onChange={(_event: unknown, checked: boolean) => { console.log("Player Bar Visibility:", checked ? "visible" : "hidden"); setPlayerBarVisible((settings.playerBarVisible = checked)); // Update styles immediately when setting changes @@ -100,11 +105,11 @@ export const Settings = () => { } }} /> - { + onChange={(_event: unknown, checked: boolean) => { console.log( "Spinning Cover Everywhere:", checked ? "enabled" : "disabled", @@ -118,11 +123,11 @@ export const Settings = () => { } }} /> - { + onChange={(_event: unknown, checked: boolean) => { console.log("Performance Mode:", checked ? "enabled" : "disabled"); setPerformanceMode((settings.performanceMode = checked)); // Update background animations immediately when setting changes @@ -134,11 +139,11 @@ export const Settings = () => { } }} /> - { + onChange={(_event: unknown, checked: boolean) => { console.log( "Background Cover Spin:", checked ? "enabled" : "disabled", @@ -253,11 +258,11 @@ export const Settings = () => { } }} /> - { + onChange={(_event: unknown, checked: boolean) => { console.log( "Settings Affect Now Playing:", checked ? "enabled" : "disabled", diff --git a/plugins/radiant-lyrics-luna/src/cover-everywhere.css b/plugins/radiant-lyrics-luna/src/cover-everywhere.css index dad629a..6bdddaf 100644 --- a/plugins/radiant-lyrics-luna/src/cover-everywhere.css +++ b/plugins/radiant-lyrics-luna/src/cover-everywhere.css @@ -47,16 +47,21 @@ .global-spinning-image.performance-mode-static { /* Keep animation enabled in performance mode */ /* Lighter blur for performance */ + /* biome-ignore lint: Required to override app styles in performance mode */ filter: blur(20px) brightness(0.4) contrast(1.2) saturate(1) !important; /* Smaller size for performance */ + /* biome-ignore lint: Required to override app layout sizes */ width: 120vw !important; + /* biome-ignore lint: Required to override app layout sizes */ height: 120vh !important; } .now-playing-background-image.performance-mode-static { /* Keep animation enabled in performance mode */ /* Optimized size and effects for performance */ + /* biome-ignore lint: Required to override inline sizes in performance mode */ width: 80vw !important; + /* biome-ignore lint: Required to override inline sizes in performance mode */ height: 80vh !important; } @@ -89,8 +94,11 @@ @media (prefers-reduced-motion: reduce) { .global-spinning-image, .now-playing-background-image { + /* biome-ignore lint: Accessibility override needs priority */ animation: none !important; + /* biome-ignore lint: Accessibility override needs priority */ transform: translate(-50%, -50%) !important; + /* biome-ignore lint: Accessibility override needs priority */ will-change: auto !important; } } @@ -99,6 +107,7 @@ .performance-mode .global-spinning-image, .performance-mode .now-playing-background-image { /* Keep animations but optimize filter effects */ + /* biome-ignore lint: Intentional override of runtime styles */ filter: blur(10px) brightness(0.4) contrast(1.1) !important; } @@ -121,6 +130,7 @@ main, [class^="_feedSidebarItemDiv"], [class^="_cellContainer"], [class^="_cellTextContainer"] { + /* biome-ignore lint: Ensure background is fully cleared under theme CSS */ background: unset !important; } @@ -129,8 +139,11 @@ main, [data-test="main-layout-sidebar-wrapper"], [class^="_bar"], [class^="_sidebarItem"]:hover { + /* biome-ignore lint: Must beat app inline styles for translucency */ background-color: rgba(0, 0, 0, 0.3) !important; + /* biome-ignore lint: Must beat app inline styles for translucency */ backdrop-filter: blur(10px) !important; + /* biome-ignore lint: Must beat app inline styles for translucency */ -webkit-backdrop-filter: blur(10px) !important; } @@ -139,20 +152,27 @@ main, .performance-mode [data-test="main-layout-sidebar-wrapper"], .performance-mode [class^="_bar"], .performance-mode [class^="_sidebarItem"]:hover { + /* biome-ignore lint: Performance mode style requires priority */ backdrop-filter: blur(5px) !important; + /* biome-ignore lint: Performance mode style requires priority */ -webkit-backdrop-filter: blur(5px) !important; } /* Feed sidebar panel - black tint background for readability */ [data-test="feed-sidebar"] { + /* biome-ignore lint: Ensure readability over media */ background-color: rgba(0, 0, 0, 0.5) !important; + /* biome-ignore lint: Ensure readability over media */ backdrop-filter: blur(10px) !important; + /* biome-ignore lint: Ensure readability over media */ -webkit-backdrop-filter: blur(10px) !important; } /* Performance mode: reduce sidebar backdrop blur */ .performance-mode [data-test="feed-sidebar"] { + /* biome-ignore lint: Performance mode style requires priority */ backdrop-filter: blur(5px) !important; + /* biome-ignore lint: Performance mode style requires priority */ -webkit-backdrop-filter: blur(5px) !important; } @@ -162,10 +182,12 @@ main, [class*="_cellContainer"], [data-test="feed-interval"], [data-test="feed-item"] { + /* biome-ignore lint: Match theme transparency */ background-color: transparent !important; } /* Remove bottom gradient */ [class^="_bottomGradient"] { + /* biome-ignore lint: Explicitly remove conflicting gradient */ display: none !important; } diff --git a/plugins/radiant-lyrics-luna/src/lyrics-glow.css b/plugins/radiant-lyrics-luna/src/lyrics-glow.css index 0752285..b455ead 100644 --- a/plugins/radiant-lyrics-luna/src/lyrics-glow.css +++ b/plugins/radiant-lyrics-luna/src/lyrics-glow.css @@ -31,10 +31,12 @@ [class*="_lyricsText"] > div > span[data-current="true"] { text-shadow: 0 0 var(--rl-glow-inner, 2px) var(--cl-glow1, #fff), + /* biome-ignore lint: Required to override app glow strength */ 0 0 var(--rl-glow-outer, 20px) var(--cl-glow2, #fff) !important; padding-left: 20px; transition-duration: 0.7s; font-size: 55px; + /* biome-ignore lint: Needs priority for active lyric color */ color: white !important; font-family: "AbyssFont", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", @@ -58,7 +60,9 @@ [class*="_lyricsText"] > div > span:hover { text-shadow: 0 0 var(--rl-glow-inner, 2px) lightgray, + /* biome-ignore lint: Hover glow should override defaults */ 0 0 var(--rl-glow-outer, 20px) lightgray !important; + /* biome-ignore lint: Hover color override */ color: lightgray !important; padding-left: 20px; transition-duration: 0.7s; @@ -69,15 +73,21 @@ /* Title text color/gradient is left to default app styling; only glow is customized. */ text-shadow: 0 0 var(--rl-glow-inner, 1px) var(--cl-glow1, #fff), + /* biome-ignore lint: Title glow needs priority */ 0 0 var(--rl-glow-outer, 30px) #fff !important; + /* biome-ignore lint: Reset vendor background clip */ -webkit-background-clip: initial !important; + /* biome-ignore lint: Reset background clip */ background-clip: initial !important; + /* biome-ignore lint: Reset vendor text fill */ -webkit-text-fill-color: initial !important; + /* biome-ignore lint: Ensure inherited color takes precedence */ color: inherit !important; } /* When track title glow setting is disabled, remove glow regardless of Colorama */ .rl-title-glow-disabled[data-test="now-playing-track-title"] { + /* biome-ignore lint: Full reset required */ text-shadow: none !important; } @@ -86,6 +96,7 @@ transition: text-shadow 0.7s ease-in-out, color 0.7s ease-in-out, + /* biome-ignore lint: Transition priority needed */ padding 0.7s ease-in-out !important; } @@ -97,6 +108,7 @@ "AbyssFont", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-weight: 700; + /* biome-ignore lint: Typography override for readability */ font-size: 38px !important; } @@ -106,13 +118,22 @@ .lyrics-glow-disabled [class*="_lyricsText"] > div > span:hover, .lyrics-glow-disabled [data-test="now-playing-track-title"], .lyrics-glow-disabled [class^="_lyricsContainer"] > div > div > span { + /* biome-ignore lint: Hard reset when disabled */ text-shadow: none !important; + /* biome-ignore lint: Hard reset when disabled */ padding-left: 0 !important; + /* biome-ignore lint: Hard reset when disabled */ transition: none !important; + /* biome-ignore lint: Hard reset when disabled */ font-size: inherit !important; + /* biome-ignore lint: Hard reset when disabled */ color: inherit !important; + /* biome-ignore lint: Hard reset when disabled */ font-family: inherit !important; + /* biome-ignore lint: Hard reset when disabled */ font-weight: inherit !important; + /* biome-ignore lint: Hard reset when disabled */ margin-bottom: inherit !important; + /* biome-ignore lint: Hard reset when disabled */ opacity: inherit !important; }