1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-16 13:31:12 +00:00

The loading experience and effect of the analysis are unified

This commit is contained in:
Tw93
2025-11-19 10:39:33 +08:00
parent 8b0396a9ff
commit 2a81c38f8f
4 changed files with 44 additions and 19 deletions

3
.gitignore vendored
View File

@@ -41,3 +41,6 @@ temp/
.claude/ .claude/
CLAUDE.md CLAUDE.md
copilot-instructions.md copilot-instructions.md
# Go build artifacts
cmd/analyze/analyze

Binary file not shown.

Binary file not shown.

View File

@@ -480,7 +480,17 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
return m, nil return m, nil
case tickMsg: case tickMsg:
if m.scanning || m.deleting || (m.isOverview && m.overviewScanning) { // Keep spinner running if scanning or deleting or if there are pending overview items
hasPending := false
if m.isOverview {
for _, entry := range m.entries {
if entry.size < 0 {
hasPending = true
break
}
}
}
if m.scanning || m.deleting || (m.isOverview && (m.overviewScanning || hasPending)) {
m.spinner = (m.spinner + 1) % len(spinnerFrames) m.spinner = (m.spinner + 1) % len(spinnerFrames)
// Update delete progress status // Update delete progress status
if m.deleting && m.deleteCount != nil { if m.deleting && m.deleteCount != nil {
@@ -709,8 +719,10 @@ func (m *model) switchToOverviewMode() tea.Cmd {
cmd := m.scheduleOverviewScans() cmd := m.scheduleOverviewScans()
if cmd == nil { if cmd == nil {
m.status = "Ready" m.status = "Ready"
return nil
} }
return cmd // Start tick to animate spinner while scanning
return tea.Batch(cmd, tickCmd())
} }
func (m model) enterSelectedDir() (tea.Model, tea.Cmd) { func (m model) enterSelectedDir() (tea.Model, tea.Cmd) {
@@ -763,7 +775,7 @@ func (m model) View() string {
if m.deleteConfirm && m.deleteTarget != nil { if m.deleteConfirm && m.deleteTarget != nil {
// Show delete confirmation prominently at the top // Show delete confirmation prominently at the top
fmt.Fprintf(&b, "%sDelete: %s (%s)? Press Delete again to confirm, ESC to cancel%s\n\n", fmt.Fprintf(&b, "%sDelete: %s (%s)? Press Delete again to confirm, ESC to cancel%s\n",
colorRed, m.deleteTarget.name, humanizeBytes(m.deleteTarget.size), colorReset) colorRed, m.deleteTarget.name, humanizeBytes(m.deleteTarget.size), colorReset)
} }
@@ -781,26 +793,38 @@ func (m model) View() string {
if allPending { if allPending {
// Show prominent loading screen for initial scan // Show prominent loading screen for initial scan
fmt.Fprintf(&b, "\n%s%s%s%s Measuring disk usage across system directories...\n", fmt.Fprintf(&b, "%s%s%s%s Analyzing disk usage, please wait...%s\n",
colorCyan, colorBold, colorCyan, colorBold,
spinnerFrames[m.spinner], spinnerFrames[m.spinner],
colorReset) colorReset, colorReset)
fmt.Fprintf(&b, "%sThis may take a moment on first run%s\n", colorGray, colorReset)
return b.String() return b.String()
} else { } else {
// Progressive scanning - show subtle indicator // Progressive scanning - show subtle indicator
fmt.Fprintf(&b, "%sSelect a location to explore:%s ", colorGray, colorReset) fmt.Fprintf(&b, "%sSelect a location to explore:%s ", colorGray, colorReset)
fmt.Fprintf(&b, "%s%s%s%s Scanning...\n", colorCyan, colorBold, spinnerFrames[m.spinner], colorReset) fmt.Fprintf(&b, "%s%s%s%s Scanning...\n\n", colorCyan, colorBold, spinnerFrames[m.spinner], colorReset)
} }
} else { } else {
fmt.Fprintf(&b, "%sSelect a location to explore:%s\n", colorGray, colorReset) // Check if there are still pending items
hasPending := false
for _, entry := range m.entries {
if entry.size < 0 {
hasPending = true
break
}
}
if hasPending {
fmt.Fprintf(&b, "%sSelect a location to explore:%s ", colorGray, colorReset)
fmt.Fprintf(&b, "%s%s%s%s Scanning...\n\n", colorCyan, colorBold, spinnerFrames[m.spinner], colorReset)
} else {
fmt.Fprintf(&b, "%sSelect a location to explore:%s\n\n", colorGray, colorReset)
}
} }
} else { } else {
fmt.Fprintf(&b, "%sAnalyze Disk%s %s%s%s", colorPurple, colorReset, colorGray, displayPath(m.path), colorReset) fmt.Fprintf(&b, "%sAnalyze Disk%s %s%s%s", colorPurple, colorReset, colorGray, displayPath(m.path), colorReset)
if !m.scanning { if !m.scanning {
fmt.Fprintf(&b, " | Total: %s", humanizeBytes(m.totalSize)) fmt.Fprintf(&b, " | Total: %s", humanizeBytes(m.totalSize))
} }
fmt.Fprintln(&b) fmt.Fprintf(&b, "\n\n")
} }
if m.deleting { if m.deleting {
@@ -810,7 +834,7 @@ func (m model) View() string {
count = atomic.LoadInt64(m.deleteCount) count = atomic.LoadInt64(m.deleteCount)
} }
fmt.Fprintf(&b, "\n%s%s%s%s Deleting: %s%s items%s removed, please wait...\n", fmt.Fprintf(&b, "%s%s%s%s Deleting: %s%s items%s removed, please wait...\n",
colorCyan, colorBold, colorCyan, colorBold,
spinnerFrames[m.spinner], spinnerFrames[m.spinner],
colorReset, colorReset,
@@ -822,7 +846,7 @@ func (m model) View() string {
if m.scanning { if m.scanning {
filesScanned, dirsScanned, bytesScanned := m.getScanProgress() filesScanned, dirsScanned, bytesScanned := m.getScanProgress()
fmt.Fprintf(&b, "\n%s%s%s%s Scanning: %s%s files%s, %s%s dirs%s, %s%s%s\n", fmt.Fprintf(&b, "%s%s%s%s Scanning: %s%s files%s, %s%s dirs%s, %s%s%s\n",
colorCyan, colorBold, colorCyan, colorBold,
spinnerFrames[m.spinner], spinnerFrames[m.spinner],
colorReset, colorReset,
@@ -842,8 +866,6 @@ func (m model) View() string {
return b.String() return b.String()
} }
fmt.Fprintln(&b)
if m.showLargeFiles { if m.showLargeFiles {
if len(m.largeFiles) == 0 { if len(m.largeFiles) == 0 {
fmt.Fprintln(&b, " No large files found (>=100MB)") fmt.Fprintln(&b, " No large files found (>=100MB)")