fix(panel): render registered settings content in the desktop UnifiedPanel

The desktop sidebar was rebuilt as UnifiedPanel but the externally-registered
settings content (discover settings gear, lyrics) was never ported -- clicking
the discover gear opened the panel to the activity feed instead of the settings,
because UnifiedPanel never read settingsContent or handled set-activity-panel-tab.
It now listens for that event, renders the registered settingsContent (which
carries its own header + back button), and resets to the feed on collapse. Fixes
discover settings and lyrics on desktop. Pre-existing since the sidebar rewrite.
This commit is contained in:
chevron7
2026-05-31 23:01:52 -05:00
parent ea363d677e
commit c715cee7b1
+46 -3
View File
@@ -1,9 +1,10 @@
"use client";
import { useState } from "react";
import { useState, useEffect } from "react";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/utils/cn";
import { useNotifications, useActiveDownloads } from "@/hooks/useNotifications";
import { useActivityPanelSettings } from "@/lib/activity-panel-settings-context";
import { ActivityIconBar, type ActivityType } from "@/features/vibe/ActivityIconBar";
import {
type VibeTab,
@@ -21,14 +22,45 @@ interface UnifiedPanelProps {
export function UnifiedPanel({ isOpen, onToggle }: UnifiedPanelProps) {
const [activeTab, setActiveTab] = useState<VibeTab>("now-playing");
const [expandedActivity, setExpandedActivity] = useState<ActivityType | null>(null);
// Externally-registered settings content (discover settings gear, lyrics).
// Pages register it via useActivityPanelSettings and open it by dispatching
// "set-activity-panel-tab" { tab: "settings" }; this panel renders it.
const [showSettings, setShowSettings] = useState(false);
const { settingsContent } = useActivityPanelSettings();
const { unreadCount } = useNotifications();
const { downloads: activeDownloads } = useActiveDownloads();
const hasActivity = unreadCount > 0 || activeDownloads.length > 0;
const handleToggleActivity = (type: ActivityType) => {
setShowSettings(false);
setExpandedActivity((prev) => (prev === type ? null : type));
};
// Reset settings view on collapse so reopening shows the feed.
const handleCollapse = () => {
setShowSettings(false);
onToggle();
};
// Respond to the cross-component tab event (discover gear, lyrics back button).
useEffect(() => {
const handleSetTab = (e: Event) => {
const tab = (e as CustomEvent<{ tab?: string }>).detail?.tab;
if (tab === "settings") {
setExpandedActivity(null);
setShowSettings(true);
} else {
setShowSettings(false);
}
};
window.addEventListener("set-activity-panel-tab", handleSetTab);
return () => window.removeEventListener("set-activity-panel-tab", handleSetTab);
}, []);
// settingsContent null (owner page unmounted) falls through to the feed via
// the `settingsContent &&` render guard -- no reset effect needed.
const settingsActive = showSettings && !!settingsContent;
return (
<div
className="shrink-0 h-full relative z-10"
@@ -43,7 +75,7 @@ export function UnifiedPanel({ isOpen, onToggle }: UnifiedPanelProps) {
>
{/* Collapsed strip */}
<div
onClick={onToggle}
onClick={handleCollapse}
className={cn(
"absolute left-0 top-0 bottom-0 w-12 flex items-center justify-center cursor-pointer hover:bg-[var(--bg-tertiary)] transition-colors z-10",
isOpen && "pointer-events-none opacity-0",
@@ -63,6 +95,15 @@ export function UnifiedPanel({ isOpen, onToggle }: UnifiedPanelProps) {
isOpen ? "opacity-100" : "opacity-0 pointer-events-none",
)}
>
{settingsActive ? (
// Externally-registered settings (discover gear / lyrics).
// The content provides its own header and back button,
// which dispatches set-activity-panel-tab to exit.
<div className="flex-1 min-h-0 overflow-hidden">
{settingsContent}
</div>
) : (
<>
{/* Header */}
<div className="flex items-center justify-between px-4 py-3 border-b border-white/5">
<div className="flex items-center gap-2">
@@ -72,7 +113,7 @@ export function UnifiedPanel({ isOpen, onToggle }: UnifiedPanelProps) {
</span>
</div>
<button
onClick={onToggle}
onClick={handleCollapse}
className="p-1 hover:bg-white/10 transition-colors"
title="Collapse panel"
>
@@ -102,6 +143,8 @@ export function UnifiedPanel({ isOpen, onToggle }: UnifiedPanelProps) {
<TabContent activeTab={activeTab} />
</>
)}
</>
)}
</div>
</div>
</div>