From 4fccaf328477650f476852ab7270756fca0c00bf Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Sat, 19 Jul 2025 14:09:02 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(ui):=20Replace=20Spin=20with?= =?UTF-8?q?=20animated=20Skeleton=20in=20UsageLogsActions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary • Swapped out the obsolete `` loader for a modern, animated Semi-UI `` implementation in `UsageLogsActions.jsx`. Details 1. Added animated Skeleton placeholders mirroring real Tag sizes (108 × 26, 65 × 26, 64 × 26). 2. Introduced `showSkeleton` state with 500 ms minimum display to eliminate flicker. 3. Leveraged existing `showStat` flag to decide when real data is ready. 4. Ensured only the three Tags are under loading state - `CompactModeToggle` renders immediately. 5. Adopted CardTable‐style `Skeleton` pattern (`loading` + `placeholder`) for consistency. 6. Removed all references to the original `Spin` component. Outcome A smoother and more consistent loading experience across devices, aligning UI behaviour with the project’s latest Skeleton standards. --- .../table/usage-logs/UsageLogsActions.jsx | 52 +++++++++++++++---- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/web/src/components/table/usage-logs/UsageLogsActions.jsx b/web/src/components/table/usage-logs/UsageLogsActions.jsx index a2e68fcd..728733d1 100644 --- a/web/src/components/table/usage-logs/UsageLogsActions.jsx +++ b/web/src/components/table/usage-logs/UsageLogsActions.jsx @@ -17,21 +17,51 @@ along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ -import React from 'react'; -import { Tag, Space, Spin } from '@douyinfe/semi-ui'; +import React, { useState, useEffect, useRef } from 'react'; +import { Tag, Space, Skeleton } from '@douyinfe/semi-ui'; import { renderQuota } from '../../../helpers'; import CompactModeToggle from '../../common/ui/CompactModeToggle'; const LogsActions = ({ stat, loadingStat, + showStat, compactMode, setCompactMode, t, }) => { + const [showSkeleton, setShowSkeleton] = useState(loadingStat); + const needSkeleton = !showStat || showSkeleton; + const loadingStartRef = useRef(Date.now()); + + useEffect(() => { + if (loadingStat) { + loadingStartRef.current = Date.now(); + setShowSkeleton(true); + } else { + const elapsed = Date.now() - loadingStartRef.current; + const remaining = Math.max(0, 500 - elapsed); + if (remaining === 0) { + setShowSkeleton(false); + } else { + const timer = setTimeout(() => setShowSkeleton(false), remaining); + return () => clearTimeout(timer); + } + } + }, [loadingStat]); + + // Skeleton placeholder layout (three tag-size blocks) + const placeholder = ( + + + + + + ); + return ( - -
+
+ + - -
- + +
); };