mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-10 22:32:16 +02:00
refactor(layout): remove Inbox component and integrate NotificationsDropdown
- Eliminated the Inbox component and its related logic from FreeLayoutDataProvider and LayoutDataProvider. - Introduced NotificationsDropdown to handle notifications in the sidebar and mobile sidebar. - Updated Sidebar and LayoutShell components to accommodate the new notifications structure, enhancing user experience and code clarity.
This commit is contained in:
parent
0592215bad
commit
93a09e1978
9 changed files with 420 additions and 219 deletions
|
|
@ -1,14 +1,12 @@
|
|||
"use client";
|
||||
|
||||
import { useAtomValue } from "jotai";
|
||||
import { AnimatePresence, motion } from "motion/react";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { activeTabAtom, type Tab } from "@/atoms/tabs/tabs.atom";
|
||||
import { Logo } from "@/components/Logo";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import type { InboxItem } from "@/hooks/use-inbox";
|
||||
import { useIsMobile } from "@/hooks/use-mobile";
|
||||
import { useElectronAPI } from "@/hooks/use-platform";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
|
@ -27,14 +25,13 @@ import {
|
|||
RightPanelToggleButton,
|
||||
} from "../right-panel/RightPanel";
|
||||
import {
|
||||
InboxSidebarContent,
|
||||
MobileSidebar,
|
||||
MobileSidebarTrigger,
|
||||
PlaygroundSidebar,
|
||||
Sidebar,
|
||||
SidebarCollapseButton,
|
||||
} from "../sidebar";
|
||||
import { SidebarSlideOutPanel } from "../sidebar/SidebarSlideOutPanel";
|
||||
import type { NotificationsDropdownData } from "../sidebar/NotificationsDropdown";
|
||||
import { TabBar } from "../tabs/TabBar";
|
||||
import { WorkspacePanel } from "./WorkspacePanel";
|
||||
|
||||
|
|
@ -80,28 +77,6 @@ function MacDesktopTitleBar({
|
|||
);
|
||||
}
|
||||
|
||||
// Per-tab data source
|
||||
interface TabDataSource {
|
||||
items: InboxItem[];
|
||||
unreadCount: number;
|
||||
loading: boolean;
|
||||
loadingMore: boolean;
|
||||
hasMore: boolean;
|
||||
loadMore: () => void;
|
||||
markAsRead: (id: number) => Promise<boolean>;
|
||||
markAllAsRead: () => Promise<boolean>;
|
||||
}
|
||||
|
||||
export type ActiveSlideoutPanel = "inbox" | null;
|
||||
|
||||
// Inbox-related props — per-tab data sources with independent loading/pagination
|
||||
interface InboxProps {
|
||||
isOpen: boolean;
|
||||
totalUnreadCount: number;
|
||||
comments: TabDataSource;
|
||||
status: TabDataSource;
|
||||
}
|
||||
|
||||
interface LayoutShellProps {
|
||||
workspaces: Workspace[];
|
||||
activeWorkspaceId: number | null;
|
||||
|
|
@ -140,11 +115,7 @@ interface LayoutShellProps {
|
|||
workspacePanelContentClassName?: string;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
// Unified slide-out panel state
|
||||
activeSlideoutPanel?: ActiveSlideoutPanel;
|
||||
onSlideoutPanelChange?: (panel: ActiveSlideoutPanel) => void;
|
||||
// Inbox props
|
||||
inbox?: InboxProps;
|
||||
notifications?: NotificationsDropdownData;
|
||||
isLoadingChats?: boolean;
|
||||
onTabSwitch?: (tab: Tab) => void;
|
||||
onTabPrefetch?: (tab: Tab) => void;
|
||||
|
|
@ -245,9 +216,7 @@ export function LayoutShell({
|
|||
workspacePanelContentClassName,
|
||||
children,
|
||||
className,
|
||||
activeSlideoutPanel = null,
|
||||
onSlideoutPanelChange,
|
||||
inbox,
|
||||
notifications,
|
||||
isLoadingChats = false,
|
||||
onTabSwitch,
|
||||
onTabPrefetch,
|
||||
|
|
@ -269,17 +238,6 @@ export function LayoutShell({
|
|||
[isCollapsed, setIsCollapsed, toggleCollapsed]
|
||||
);
|
||||
|
||||
const closeSlideout = useCallback(
|
||||
(open: boolean) => {
|
||||
if (!open) onSlideoutPanelChange?.(null);
|
||||
},
|
||||
[onSlideoutPanelChange]
|
||||
);
|
||||
|
||||
const anySlideOutOpen = activeSlideoutPanel !== null;
|
||||
|
||||
const panelAriaLabel = activeSlideoutPanel === "inbox" ? "Inbox" : "Panel";
|
||||
|
||||
// Mobile layout
|
||||
if (isMobile) {
|
||||
return (
|
||||
|
|
@ -316,6 +274,7 @@ export function LayoutShell({
|
|||
onUserSettings={onUserSettings}
|
||||
onAnnouncements={onAnnouncements}
|
||||
announcementUnreadCount={announcementUnreadCount}
|
||||
notifications={notifications}
|
||||
onLogout={onLogout}
|
||||
pageUsage={pageUsage}
|
||||
theme={theme}
|
||||
|
|
@ -335,34 +294,6 @@ export function LayoutShell({
|
|||
{children}
|
||||
</main>
|
||||
)}
|
||||
|
||||
{/* Mobile unified slide-out panel */}
|
||||
<SidebarSlideOutPanel
|
||||
open={anySlideOutOpen}
|
||||
onOpenChange={closeSlideout}
|
||||
ariaLabel={panelAriaLabel}
|
||||
>
|
||||
<AnimatePresence mode="popLayout" initial={false}>
|
||||
{activeSlideoutPanel === "inbox" && inbox && (
|
||||
<motion.div
|
||||
key="inbox"
|
||||
className="h-full flex flex-col"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
>
|
||||
<InboxSidebarContent
|
||||
onOpenChange={(open) => closeSlideout(open)}
|
||||
comments={inbox.comments}
|
||||
status={inbox.status}
|
||||
totalUnreadCount={inbox.totalUnreadCount}
|
||||
onCloseMobileSidebar={() => setMobileMenuOpen(false)}
|
||||
/>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</SidebarSlideOutPanel>
|
||||
</div>
|
||||
</TooltipProvider>
|
||||
</SidebarProvider>
|
||||
|
|
@ -400,6 +331,7 @@ export function LayoutShell({
|
|||
onUserSettings={onUserSettings}
|
||||
onAnnouncements={onAnnouncements}
|
||||
announcementUnreadCount={announcementUnreadCount}
|
||||
notifications={notifications}
|
||||
onLogout={onLogout}
|
||||
theme={theme}
|
||||
setTheme={setTheme}
|
||||
|
|
@ -425,10 +357,7 @@ export function LayoutShell({
|
|||
className={cn(
|
||||
"relative hidden md:flex shrink-0 z-20 -mr-2 bg-panel",
|
||||
isMacDesktop
|
||||
? cn(
|
||||
"border-t border-r",
|
||||
!showPlaygroundSidebar && "rounded-tl-xl border-l"
|
||||
)
|
||||
? cn("border-t border-r", !showPlaygroundSidebar && "rounded-tl-xl border-l")
|
||||
: "border-r"
|
||||
)}
|
||||
>
|
||||
|
|
@ -491,33 +420,6 @@ export function LayoutShell({
|
|||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Unified slide-out panel — shell stays open, content cross-fades */}
|
||||
<SidebarSlideOutPanel
|
||||
open={anySlideOutOpen}
|
||||
onOpenChange={closeSlideout}
|
||||
ariaLabel={panelAriaLabel}
|
||||
>
|
||||
<AnimatePresence mode="popLayout" initial={false}>
|
||||
{activeSlideoutPanel === "inbox" && inbox && (
|
||||
<motion.div
|
||||
key="inbox"
|
||||
className="h-full flex flex-col"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
>
|
||||
<InboxSidebarContent
|
||||
onOpenChange={(open) => closeSlideout(open)}
|
||||
comments={inbox.comments}
|
||||
status={inbox.status}
|
||||
totalUnreadCount={inbox.totalUnreadCount}
|
||||
/>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</SidebarSlideOutPanel>
|
||||
</div>
|
||||
|
||||
<DesktopWorkspaceRegion>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue