mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-05 01:50:27 +08:00
feat: 优化文件管理器的加载体验,异步加载新鲜度数据并添加加载状态指示
This commit is contained in:
@@ -90,7 +90,9 @@
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 400px;
|
||||
gap: 1.5rem;
|
||||
align-items: start;
|
||||
align-items: stretch;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
|
||||
@@ -94,6 +94,8 @@
|
||||
.claude-manager-column.center {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.claude-manager-column.right {
|
||||
@@ -286,11 +288,15 @@
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 1rem;
|
||||
min-height: 0;
|
||||
background: hsl(var(--muted) / 0.3);
|
||||
border-radius: 0 0 0.5rem 0.5rem;
|
||||
}
|
||||
|
||||
.markdown-content {
|
||||
line-height: 1.6;
|
||||
color: hsl(var(--foreground));
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.markdown-content h1 {
|
||||
@@ -507,10 +513,14 @@
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
min-height: 200px;
|
||||
color: hsl(var(--muted-foreground));
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
background: hsl(var(--muted) / 0.3);
|
||||
border-radius: 0.5rem;
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
||||
.empty-state i {
|
||||
@@ -763,6 +773,18 @@
|
||||
color: hsl(0, 72%, 51%);
|
||||
}
|
||||
|
||||
.freshness-badge.loading {
|
||||
background: hsl(var(--muted));
|
||||
color: hsl(var(--muted-foreground));
|
||||
min-width: 28px;
|
||||
animation: pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 0.5; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
/* File tree item freshness states */
|
||||
.file-tree-item.freshness-stale {
|
||||
border-left: 2px solid hsl(0, 72%, 51%);
|
||||
@@ -846,6 +868,21 @@
|
||||
color: hsl(38, 92%, 50%);
|
||||
}
|
||||
|
||||
/* Freshness loading state */
|
||||
.freshness-loading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
padding: 1.5rem;
|
||||
color: hsl(var(--muted-foreground));
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.freshness-loading i {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
* Responsive Design
|
||||
* ======================================== */
|
||||
|
||||
@@ -37,11 +37,10 @@ async function renderClaudeManager() {
|
||||
'<p>' + t('common.loading') + '</p>' +
|
||||
'</div>';
|
||||
|
||||
// Load data
|
||||
// Load file data first (fast operation)
|
||||
await loadClaudeFiles();
|
||||
await loadFreshnessData();
|
||||
|
||||
// Render layout
|
||||
// Render layout immediately without waiting for freshness data
|
||||
container.innerHTML = '<div class="claude-manager-view">' +
|
||||
'<div class="claude-manager-header">' +
|
||||
'<div class="claude-manager-header-left">' +
|
||||
@@ -64,13 +63,34 @@ async function renderClaudeManager() {
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
// Render each column
|
||||
// Render each column immediately (without freshness data)
|
||||
renderFileTree();
|
||||
renderFileViewer();
|
||||
renderFileMetadata();
|
||||
|
||||
// Initialize Lucide icons
|
||||
if (window.lucide) lucide.createIcons();
|
||||
|
||||
// Load freshness data asynchronously in the background (non-blocking)
|
||||
loadFreshnessDataAsync();
|
||||
}
|
||||
|
||||
// Async freshness loader - loads in background and updates UI when ready
|
||||
function loadFreshnessDataAsync() {
|
||||
// Use setTimeout to ensure UI is rendered first
|
||||
setTimeout(async function() {
|
||||
try {
|
||||
await loadFreshnessData();
|
||||
// Re-render file tree and metadata with freshness data
|
||||
renderFileTree();
|
||||
if (selectedFile) {
|
||||
renderFileMetadata();
|
||||
}
|
||||
if (window.lucide) lucide.createIcons();
|
||||
} catch (error) {
|
||||
console.error('Error loading freshness data in background:', error);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// ========== Data Loading ==========
|
||||
@@ -88,9 +108,14 @@ async function loadClaudeFiles() {
|
||||
|
||||
async function refreshClaudeFiles() {
|
||||
await loadClaudeFiles();
|
||||
await loadFreshnessData();
|
||||
await renderClaudeManager();
|
||||
// Re-render file tree immediately
|
||||
renderFileTree();
|
||||
renderFileViewer();
|
||||
renderFileMetadata();
|
||||
if (window.lucide) lucide.createIcons();
|
||||
addGlobalNotification('success', t('claudeManager.refreshed'), null, 'CLAUDE.md');
|
||||
// Load freshness data in background
|
||||
loadFreshnessDataAsync();
|
||||
}
|
||||
|
||||
// ========== Freshness Data Loading ==========
|
||||
@@ -241,6 +266,9 @@ function renderFileTreeItem(file, indentLevel) {
|
||||
var freshnessClass = '';
|
||||
var freshnessBadge = '';
|
||||
|
||||
// Check if freshness data is loaded (freshnessSummary is set after load)
|
||||
var freshnessLoaded = freshnessSummary !== null || Object.keys(freshnessData).length > 0;
|
||||
|
||||
if (fd) {
|
||||
if (fd.freshness >= 75) {
|
||||
freshnessClass = ' freshness-good';
|
||||
@@ -252,6 +280,9 @@ function renderFileTreeItem(file, indentLevel) {
|
||||
freshnessClass = ' freshness-stale';
|
||||
freshnessBadge = '<span class="freshness-badge stale">' + fd.freshness + '%</span>';
|
||||
}
|
||||
} else if (!freshnessLoaded) {
|
||||
// Show loading badge while freshness data is being fetched
|
||||
freshnessBadge = '<span class="freshness-badge loading">...</span>';
|
||||
}
|
||||
|
||||
return '<div class="file-tree-item' + freshnessClass + (isSelected ? ' selected' : '') + '" ' +
|
||||
@@ -520,6 +551,8 @@ function renderFileMetadata() {
|
||||
|
||||
// Freshness section
|
||||
var fd = freshnessData[selectedFile.path];
|
||||
var freshnessLoaded = freshnessSummary !== null || Object.keys(freshnessData).length > 0;
|
||||
|
||||
if (fd) {
|
||||
var freshnessBarClass = fd.freshness >= 75 ? 'good' : fd.freshness >= 50 ? 'warn' : 'stale';
|
||||
html += '<div class="metadata-section freshness-section">' +
|
||||
@@ -548,6 +581,15 @@ function renderFileMetadata() {
|
||||
'<i data-lucide="check-circle" class="w-4 h-4"></i> ' + (t('claudeManager.markAsUpdated') || 'Mark as Updated') +
|
||||
'</button>' +
|
||||
'</div>';
|
||||
} else if (!freshnessLoaded) {
|
||||
// Show loading state while freshness data is being fetched
|
||||
html += '<div class="metadata-section freshness-section">' +
|
||||
'<h4><i data-lucide="activity" class="w-4 h-4"></i> ' + (t('claudeManager.freshness') || 'Freshness') + '</h4>' +
|
||||
'<div class="freshness-loading">' +
|
||||
'<i data-lucide="loader-2" class="w-5 h-5 animate-spin"></i>' +
|
||||
'<span>' + (t('claudeManager.loadingFreshness') || 'Loading freshness data...') + '</span>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
html += '<div class="metadata-section">' +
|
||||
|
||||
Reference in New Issue
Block a user