From 2e1375ce2dac1a1c69be992d89f5bfde83239268 Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Sun, 8 Nov 2026 19:14:42 +0000 Subject: [PATCH] Enhance Dashboard Navigation and Live Activities Integration - Updated vite.config.js to optimize React chunking for antd imports, preventing issues with hooks. - Added new LiveActivities component to manage and display real-time activity notifications in the dashboard. - Refactored DashboardNavigation component to include LiveActivities, improving user interaction with activity notifications. - Introduced new CSS styles for dashboard navigation activities, enhancing visual feedback and responsiveness. --- assets/stylesheets/App.css | 136 ++++++ .../Dashboard/common/DashboardNavigation.jsx | 49 +- .../Dashboard/common/LiveActivities.jsx | 450 ++++++++++++++++++ vite.config.js | 21 +- 4 files changed, 636 insertions(+), 20 deletions(-) create mode 100644 src/components/Dashboard/common/LiveActivities.jsx diff --git a/assets/stylesheets/App.css b/assets/stylesheets/App.css index ac27a02f..01677eec 100644 --- a/assets/stylesheets/App.css +++ b/assets/stylesheets/App.css @@ -4208,6 +4208,142 @@ body.objectKanbanColumnResizing * { stroke-width: 12px; } +.dashboard-navigation-activity-cluster { + gap: 0; + transition: gap 0.3s cubic-bezier(0.2, 0, 0, 1); +} + +.dashboard-navigation-activity-cluster:has(.live-activities-open) { + gap: var(--dashboard-navigation-gap, 8px); +} + +.live-activities { + overflow: hidden; + border-radius: 12px; + flex: 0 0 auto; + transition: + width 0.3s cubic-bezier(0.2, 0, 0, 1), + opacity 0.3s cubic-bezier(0.2, 0, 0, 1); +} + +.live-activities-row { + display: flex; + align-items: stretch; + height: 100%; + width: max-content; +} + +.live-activity-slot { + overflow: hidden; + flex: 0 0 auto; + height: 100%; + position: relative; + transition: width 0.3s cubic-bezier(0.2, 0, 0, 1); +} + +.live-activity { + position: absolute; + top: 0; + left: 0; + display: inline-flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + padding: 0; + border: 0; + border-radius: 0; + overflow: hidden; + cursor: pointer; + line-height: 1; + container-type: inline-size; + background: color-mix(in srgb, var(--live-activity-color) 20%, transparent); + transition: background 0.2s ease; +} + +.live-activity:hover { + background: color-mix(in srgb, var(--live-activity-color) 35%, transparent); +} + +.live-activity-progress, +.live-activity-flash { + position: absolute; + top: 0; + bottom: 0; + left: 0; + pointer-events: none; +} + +.live-activity-flash { + right: 0; +} + +.live-activity-progress { + overflow: hidden; +} + +.live-activity-progress-fill { + position: absolute; + inset: 0; + opacity: 0.22; + transition: opacity 0.2s ease; +} + +.live-activity:hover .live-activity-progress-fill { + opacity: 0.4; +} + +.live-activity-progress-wave { + position: absolute; + inset-block: 0; + inset-inline-start: -80cqw; + width: 240cqw; + background: repeating-linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0, + rgba(255, 255, 255, 0.05) 40cqw, + rgba(255, 255, 255, 0) 80cqw + ); + animation: live-activity-progress-wave 1s linear infinite; +} + +@keyframes live-activity-progress-wave { + 0% { + transform: translateX(0); + } + 100% { + transform: translateX(calc(100% / 3)); + } +} + +.live-activity-icon { + position: relative; + z-index: 1; + display: flex; + line-height: 1; + color: var(--color-text); +} + +@keyframes live-activity-flash { + 0%, + 100% { + opacity: var(--live-activity-flash-from); + } + 50% { + opacity: var(--live-activity-flash-to); + } +} + +.live-activity-flash { + --live-activity-flash-from: 0; + --live-activity-flash-to: 0.2; + animation: live-activity-flash 2s ease-in-out infinite; +} + +.live-activity:hover .live-activity-flash { + --live-activity-flash-from: 0.12; + --live-activity-flash-to: 0.45; +} + .printerQueue.ant-steps.ant-steps-vertical > .ant-steps-item:last-child .ant-steps-item-content { diff --git a/src/components/Dashboard/common/DashboardNavigation.jsx b/src/components/Dashboard/common/DashboardNavigation.jsx index 35efee2f..f640c00d 100644 --- a/src/components/Dashboard/common/DashboardNavigation.jsx +++ b/src/components/Dashboard/common/DashboardNavigation.jsx @@ -17,7 +17,8 @@ import { Badge, Divider, Typography, - Popover + Popover, + theme } from 'antd' import classNames from 'classnames' import { AuthContext } from '../context/AuthContext' @@ -46,6 +47,7 @@ import SettingsIcon from '../../Icons/SettingsIcon' import { ElectronContext } from '../context/ElectronContext' import DashboardWindowButtons from './DashboardWindowButtons' import DashboardDevControls from './DashboardDevControls' +import LiveActivities from './LiveActivities' import WindowAppMenu from './WindowAppMenu' import WebAppSwitcher from './WebAppSwitcher' import DashboardTabs from './DashboardTabs' @@ -148,6 +150,8 @@ const DashboardNavigationTrailingItems = memo( onNotifications, onCheckUpdates }) { + const { token } = theme.useToken() + return ( {controlsReady ? ( @@ -165,25 +169,34 @@ const DashboardNavigationTrailingItems = memo( onClick={onSearch} /> - - + - + + + ) + })} + + + ) +} + +export default LiveActivities diff --git a/vite.config.js b/vite.config.js index 276089ce..085c0a6c 100644 --- a/vite.config.js +++ b/vite.config.js @@ -50,12 +50,29 @@ export default defineConfig({ three: path.resolve(__dirname, 'node_modules/three'), ...codemirrorSingletons }, - dedupe: Object.keys(codemirrorSingletons) + // Deep `antd/es/*` imports are optimized separately from the app entry. + // Without dedupe they get their own React chunk, and hooks throw + // "Cannot read properties of null (reading 'useContext')". + dedupe: ['react', 'react-dom', ...Object.keys(codemirrorSingletons)] }, optimizeDeps: { // Do not prebundle CodeMirror — pnpm + esbuild duplicates @codemirror/state // and breaks FacetProvider instanceof checks. - include: ['@ant-design/icons'], + // Include antd's internal entry points up front so they share the app's + // React chunk instead of being discovered later and bundled apart. + include: [ + 'react', + 'react-dom', + 'react-dom/client', + 'react/jsx-dev-runtime', + 'antd', + 'antd/es/config-provider/hooks/useCSSVarCls', + 'antd/es/config-provider/hooks/useSize', + 'antd/es/input/style', + 'antd/es/space/Compact', + 'antd/es/layout/layout', + '@ant-design/icons' + ], exclude: [ '@uiw/react-codemirror', 'codemirror',