mirror of
https://github.com/acedanger/shell.git
synced 2025-12-06 00:00:13 -08:00
refactor: Clean up whitespace and improve formatting in backup update logic
This commit is contained in:
124
tui/main.go
124
tui/main.go
@@ -479,10 +479,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
if m.backupStatus[msg.service] == nil {
|
if m.backupStatus[msg.service] == nil {
|
||||||
m.backupStatus[msg.service] = &BackupStatus{}
|
m.backupStatus[msg.service] = &BackupStatus{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create context for this backup
|
// Create context for this backup
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
m.backupStatus[msg.service].Service = msg.service
|
m.backupStatus[msg.service].Service = msg.service
|
||||||
m.backupStatus[msg.service].Status = "running"
|
m.backupStatus[msg.service].Status = "running"
|
||||||
m.backupStatus[msg.service].LastRun = time.Now()
|
m.backupStatus[msg.service].LastRun = time.Now()
|
||||||
@@ -490,9 +490,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.backupStatus[msg.service].Progress = 0
|
m.backupStatus[msg.service].Progress = 0
|
||||||
m.backupStatus[msg.service].Context = ctx
|
m.backupStatus[msg.service].Context = ctx
|
||||||
m.backupStatus[msg.service].Cancel = cancel
|
m.backupStatus[msg.service].Cancel = cancel
|
||||||
|
|
||||||
m.viewport.SetContent(fmt.Sprintf("🚀 Starting backup for %s...\n\nInitializing backup process...\nPress 'x' to cancel if needed.", msg.service))
|
m.viewport.SetContent(fmt.Sprintf("🚀 Starting backup for %s...\n\nInitializing backup process...\nPress 'x' to cancel if needed.", msg.service))
|
||||||
|
|
||||||
// Start progress ticker for time-based progress estimation
|
// Start progress ticker for time-based progress estimation
|
||||||
cmds = append(cmds, m.startProgressTicker(msg.service))
|
cmds = append(cmds, m.startProgressTicker(msg.service))
|
||||||
|
|
||||||
@@ -547,18 +547,18 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.backupStatus[msg.service].EndTime = time.Now()
|
m.backupStatus[msg.service].EndTime = time.Now()
|
||||||
m.backupStatus[msg.service].Duration = m.backupStatus[msg.service].EndTime.Sub(m.backupStatus[msg.service].StartTime).String()
|
m.backupStatus[msg.service].Duration = m.backupStatus[msg.service].EndTime.Sub(m.backupStatus[msg.service].StartTime).String()
|
||||||
m.backupStatus[msg.service].Progress = 100
|
m.backupStatus[msg.service].Progress = 100
|
||||||
|
|
||||||
// Clean up context
|
// Clean up context
|
||||||
if m.backupStatus[msg.service].Cancel != nil {
|
if m.backupStatus[msg.service].Cancel != nil {
|
||||||
m.backupStatus[msg.service].Cancel()
|
m.backupStatus[msg.service].Cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete(m.runningBackups, msg.service)
|
delete(m.runningBackups, msg.service)
|
||||||
|
|
||||||
// Parse output for additional info
|
// Parse output for additional info
|
||||||
lines := strings.Split(msg.output, "\n")
|
lines := strings.Split(msg.output, "\n")
|
||||||
var summary strings.Builder
|
var summary strings.Builder
|
||||||
|
|
||||||
// Extract meaningful summary information
|
// Extract meaningful summary information
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
if strings.Contains(line, "Total files:") ||
|
if strings.Contains(line, "Total files:") ||
|
||||||
@@ -569,18 +569,18 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
summary.WriteString("📊 " + strings.TrimSpace(line) + "\n")
|
summary.WriteString("📊 " + strings.TrimSpace(line) + "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
summaryText := summary.String()
|
summaryText := summary.String()
|
||||||
if summaryText == "" {
|
if summaryText == "" {
|
||||||
summaryText = "📊 Backup completed successfully"
|
summaryText = "📊 Backup completed successfully"
|
||||||
}
|
}
|
||||||
|
|
||||||
duration := ""
|
duration := ""
|
||||||
if m.backupStatus[msg.service] != nil {
|
if m.backupStatus[msg.service] != nil {
|
||||||
duration = m.backupStatus[msg.service].Duration
|
duration = m.backupStatus[msg.service].Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
m.viewport.SetContent(fmt.Sprintf("✅ Backup completed successfully for %s!\n\nDuration: %s\n\n%s\n\n📋 Full Output:\n%s",
|
m.viewport.SetContent(fmt.Sprintf("✅ Backup completed successfully for %s!\n\nDuration: %s\n\n%s\n\n📋 Full Output:\n%s",
|
||||||
msg.service, duration, summaryText, msg.output))
|
msg.service, duration, summaryText, msg.output))
|
||||||
|
|
||||||
case backupErrorMsg:
|
case backupErrorMsg:
|
||||||
@@ -589,19 +589,19 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.backupStatus[msg.service].Error = msg.error
|
m.backupStatus[msg.service].Error = msg.error
|
||||||
m.backupStatus[msg.service].EndTime = time.Now()
|
m.backupStatus[msg.service].EndTime = time.Now()
|
||||||
m.backupStatus[msg.service].Duration = m.backupStatus[msg.service].EndTime.Sub(m.backupStatus[msg.service].StartTime).String()
|
m.backupStatus[msg.service].Duration = m.backupStatus[msg.service].EndTime.Sub(m.backupStatus[msg.service].StartTime).String()
|
||||||
|
|
||||||
// Clean up context
|
// Clean up context
|
||||||
if m.backupStatus[msg.service].Cancel != nil {
|
if m.backupStatus[msg.service].Cancel != nil {
|
||||||
m.backupStatus[msg.service].Cancel()
|
m.backupStatus[msg.service].Cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete(m.runningBackups, msg.service)
|
delete(m.runningBackups, msg.service)
|
||||||
|
|
||||||
duration := ""
|
duration := ""
|
||||||
if m.backupStatus[msg.service] != nil {
|
if m.backupStatus[msg.service] != nil {
|
||||||
duration = m.backupStatus[msg.service].Duration
|
duration = m.backupStatus[msg.service].Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide helpful error analysis
|
// Provide helpful error analysis
|
||||||
var errorAnalysis string
|
var errorAnalysis string
|
||||||
if strings.Contains(msg.error, "permission denied") {
|
if strings.Contains(msg.error, "permission denied") {
|
||||||
@@ -613,8 +613,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
} else if strings.Contains(msg.error, "space") {
|
} else if strings.Contains(msg.error, "space") {
|
||||||
errorAnalysis = "\n💡 This might be a disk space issue. Check available storage."
|
errorAnalysis = "\n💡 This might be a disk space issue. Check available storage."
|
||||||
}
|
}
|
||||||
|
|
||||||
m.viewport.SetContent(fmt.Sprintf("❌ Backup failed for %s!\n\nDuration: %s%s\n\n🚨 Error Details:\n%s",
|
m.viewport.SetContent(fmt.Sprintf("❌ Backup failed for %s!\n\nDuration: %s%s\n\n🚨 Error Details:\n%s",
|
||||||
msg.service, duration, errorAnalysis, msg.error))
|
msg.service, duration, errorAnalysis, msg.error))
|
||||||
|
|
||||||
case spinner.TickMsg:
|
case spinner.TickMsg:
|
||||||
@@ -663,11 +663,11 @@ func (m *Model) updateViewportForRunningService(service string, outputForDisplay
|
|||||||
totalEstimatedDuration := time.Duration(totalEstimatedRaw)
|
totalEstimatedDuration := time.Duration(totalEstimatedRaw)
|
||||||
remainingDuration := totalEstimatedDuration - elapsed
|
remainingDuration := totalEstimatedDuration - elapsed
|
||||||
if remainingDuration > 0 {
|
if remainingDuration > 0 {
|
||||||
etaStr = fmt.Sprintf("\\nETA: %s", remainingDuration.Round(time.Second))
|
etaStr = fmt.Sprintf("\nETA: %s", remainingDuration.Round(time.Second))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.viewport.SetContent(fmt.Sprintf("⏳ Backup in progress for %s...\\n\\n%s %d%%%%\\nElapsed: %s%s\\n\\n📋 Latest output:\\n%s\\n\\nPress 'x' to stop the backup.",
|
m.viewport.SetContent(fmt.Sprintf("⏳ Backup in progress for %s...\n\n%s %d%%\nElapsed: %s%s\n\n📋 Latest output:\n%s\n\nPress 'x' to stop the backup.",
|
||||||
service, progressBar, progress, elapsed.Round(time.Second), etaStr, outputForDisplay))
|
service, progressBar, progress, elapsed.Round(time.Second), etaStr, outputForDisplay))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,7 +702,7 @@ func (m Model) View() string {
|
|||||||
if m.activePanel == 1 {
|
if m.activePanel == 1 {
|
||||||
viewportStyle = viewportStyle.BorderStyle(lipgloss.ThickBorder()).BorderForeground(lipgloss.Color("#7D56F4"))
|
viewportStyle = viewportStyle.BorderStyle(lipgloss.ThickBorder()).BorderForeground(lipgloss.Color("#7D56F4"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add view indicator to viewport title
|
// Add view indicator to viewport title
|
||||||
viewportTitle := ""
|
viewportTitle := ""
|
||||||
switch m.currentView {
|
switch m.currentView {
|
||||||
@@ -715,7 +715,7 @@ func (m Model) View() string {
|
|||||||
default:
|
default:
|
||||||
viewportTitle = "💻 Output"
|
viewportTitle = "💻 Output"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Layout based on active panel
|
// Layout based on active panel
|
||||||
return lipgloss.JoinVertical(lipgloss.Left,
|
return lipgloss.JoinVertical(lipgloss.Left,
|
||||||
titleStyle.Render("🔧 Media & Plex Backup Manager"),
|
titleStyle.Render("🔧 Media & Plex Backup Manager"),
|
||||||
@@ -833,7 +833,7 @@ func (m *Model) showStatus() {
|
|||||||
for _, service := range services {
|
for _, service := range services {
|
||||||
status := m.backupStatus[service]
|
status := m.backupStatus[service]
|
||||||
content.WriteString(fmt.Sprintf("🔧 Service: %s\n", strings.ToUpper(service)))
|
content.WriteString(fmt.Sprintf("🔧 Service: %s\n", strings.ToUpper(service)))
|
||||||
|
|
||||||
// Status with emoji
|
// Status with emoji
|
||||||
statusIcon := "⭕"
|
statusIcon := "⭕"
|
||||||
switch status.Status {
|
switch status.Status {
|
||||||
@@ -847,34 +847,34 @@ func (m *Model) showStatus() {
|
|||||||
statusIcon = "🛑"
|
statusIcon = "🛑"
|
||||||
}
|
}
|
||||||
content.WriteString(fmt.Sprintf(" Status: %s %s\n", statusIcon, status.Status))
|
content.WriteString(fmt.Sprintf(" Status: %s %s\n", statusIcon, status.Status))
|
||||||
|
|
||||||
if !status.LastRun.IsZero() {
|
if !status.LastRun.IsZero() {
|
||||||
content.WriteString(fmt.Sprintf(" Last Run: %s\n", status.LastRun.Format("2006-01-02 15:04:05")))
|
content.WriteString(fmt.Sprintf(" Last Run: %s\n", status.LastRun.Format("2006-01-02 15:04:05")))
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.Duration != "" {
|
if status.Duration != "" {
|
||||||
content.WriteString(fmt.Sprintf(" Duration: %s\n", status.Duration))
|
content.WriteString(fmt.Sprintf(" Duration: %s\n", status.Duration))
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.Progress > 0 && status.Status == "running" {
|
if status.Progress > 0 && status.Status == "running" {
|
||||||
content.WriteString(fmt.Sprintf(" Progress: %d%%\n", status.Progress))
|
content.WriteString(fmt.Sprintf(" Progress: %d%%\n", status.Progress))
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.BackupSize != "" {
|
if status.BackupSize != "" {
|
||||||
content.WriteString(fmt.Sprintf(" Size: %s\n", status.BackupSize))
|
content.WriteString(fmt.Sprintf(" Size: %s\n", status.BackupSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.FilesCount > 0 {
|
if status.FilesCount > 0 {
|
||||||
content.WriteString(fmt.Sprintf(" Files: %d\n", status.FilesCount))
|
content.WriteString(fmt.Sprintf(" Files: %d\n", status.FilesCount))
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.Error != "" {
|
if status.Error != "" {
|
||||||
content.WriteString(fmt.Sprintf(" Error: %s\n", status.Error[:min(100, len(status.Error))]))
|
content.WriteString(fmt.Sprintf(" Error: %s\n", status.Error[:min(100, len(status.Error))]))
|
||||||
}
|
}
|
||||||
|
|
||||||
content.WriteString("\n")
|
content.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add summary
|
// Add summary
|
||||||
running := 0
|
running := 0
|
||||||
success := 0
|
success := 0
|
||||||
@@ -889,7 +889,7 @@ func (m *Model) showStatus() {
|
|||||||
failed++
|
failed++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
content.WriteString("📊 SUMMARY:\n")
|
content.WriteString("📊 SUMMARY:\n")
|
||||||
content.WriteString(fmt.Sprintf(" Running: %d | Success: %d | Failed: %d\n", running, success, failed))
|
content.WriteString(fmt.Sprintf(" Running: %d | Success: %d | Failed: %d\n", running, success, failed))
|
||||||
}
|
}
|
||||||
@@ -916,7 +916,7 @@ func (m *Model) showConfig() {
|
|||||||
if len(item.args) > 0 {
|
if len(item.args) > 0 {
|
||||||
content.WriteString(fmt.Sprintf(" Args: %s\n", strings.Join(item.args, " ")))
|
content.WriteString(fmt.Sprintf(" Args: %s\n", strings.Join(item.args, " ")))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if script exists
|
// Check if script exists
|
||||||
if _, err := os.Stat(item.script); os.IsNotExist(err) {
|
if _, err := os.Stat(item.script); os.IsNotExist(err) {
|
||||||
content.WriteString(" ⚠️ Status: Script not found\n")
|
content.WriteString(" ⚠️ Status: Script not found\n")
|
||||||
@@ -950,10 +950,10 @@ func (m *Model) stopBackup(service string, process *RunningProcess) tea.Cmd {
|
|||||||
if process.Cancel != nil {
|
if process.Cancel != nil {
|
||||||
process.Cancel()
|
process.Cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give process time to shut down gracefully
|
// Give process time to shut down gracefully
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
// Force kill if still running
|
// Force kill if still running
|
||||||
if process.Cmd != nil && process.Cmd.Process != nil {
|
if process.Cmd != nil && process.Cmd.Process != nil {
|
||||||
if process.Cmd.ProcessState == nil || !process.Cmd.ProcessState.Exited() {
|
if process.Cmd.ProcessState == nil || !process.Cmd.ProcessState.Exited() {
|
||||||
@@ -977,11 +977,11 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
|||||||
// Create context for cancellation
|
// Create context for cancellation
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Execute the backup script with context
|
// Execute the backup script with context
|
||||||
cmd := exec.CommandContext(ctx, item.script, item.args...)
|
cmd := exec.CommandContext(ctx, item.script, item.args...)
|
||||||
cmd.Dir = m.shellPath
|
cmd.Dir = m.shellPath
|
||||||
|
|
||||||
// Create pipes for stdout and stderr
|
// Create pipes for stdout and stderr
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -990,7 +990,7 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
|||||||
error: fmt.Sprintf("Failed to create stdout pipe: %s", err.Error()),
|
error: fmt.Sprintf("Failed to create stdout pipe: %s", err.Error()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stderr, err := cmd.StderrPipe()
|
stderr, err := cmd.StderrPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return backupErrorMsg{
|
return backupErrorMsg{
|
||||||
@@ -998,7 +998,7 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
|||||||
error: fmt.Sprintf("Failed to create stderr pipe: %s", err.Error()),
|
error: fmt.Sprintf("Failed to create stderr pipe: %s", err.Error()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the command
|
// Start the command
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return backupErrorMsg{
|
return backupErrorMsg{
|
||||||
@@ -1006,14 +1006,14 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
|||||||
error: fmt.Sprintf("Failed to start backup: %s", err.Error()),
|
error: fmt.Sprintf("Failed to start backup: %s", err.Error()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var outputBuilder strings.Builder
|
var outputBuilder strings.Builder
|
||||||
var allOutput []string
|
var allOutput []string
|
||||||
|
|
||||||
// Monitor stdout and stderr in goroutines
|
// Monitor stdout and stderr in goroutines
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(2)
|
wg.Add(2)
|
||||||
|
|
||||||
// Read stdout
|
// Read stdout
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
@@ -1024,7 +1024,7 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
|||||||
allOutput = append(allOutput, line)
|
allOutput = append(allOutput, line)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Read stderr
|
// Read stderr
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
@@ -1035,21 +1035,21 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
|||||||
allOutput = append(allOutput, "[STDERR] "+line)
|
allOutput = append(allOutput, "[STDERR] "+line)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Wait for the command to complete
|
// Wait for the command to complete
|
||||||
err = cmd.Wait()
|
err = cmd.Wait()
|
||||||
|
|
||||||
// Wait for output readers to finish
|
// Wait for output readers to finish
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
finalOutput := outputBuilder.String()
|
finalOutput := outputBuilder.String()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Check if it was cancelled
|
// Check if it was cancelled
|
||||||
if ctx.Err() == context.Canceled {
|
if ctx.Err() == context.Canceled {
|
||||||
return backupStopMsg{service: item.service}
|
return backupStopMsg{service: item.service}
|
||||||
}
|
}
|
||||||
|
|
||||||
return backupErrorMsg{
|
return backupErrorMsg{
|
||||||
service: item.service,
|
service: item.service,
|
||||||
error: fmt.Sprintf("Backup failed: %s\n\n📋 Output:\n%s", err.Error(), finalOutput),
|
error: fmt.Sprintf("Backup failed: %s\n\n📋 Output:\n%s", err.Error(), finalOutput),
|
||||||
@@ -1068,7 +1068,7 @@ func estimateProgress(output []string, service string) int {
|
|||||||
if len(output) == 0 {
|
if len(output) == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
switch service {
|
switch service {
|
||||||
case "plex":
|
case "plex":
|
||||||
// Plex backup stages: stop service (10%), backup files (60%), verify (20%), archive (10%)
|
// Plex backup stages: stop service (10%), backup files (60%), verify (20%), archive (10%)
|
||||||
@@ -1080,7 +1080,7 @@ func estimateProgress(output []string, service string) int {
|
|||||||
"archiving": 90,
|
"archiving": 90,
|
||||||
"completed": 100,
|
"completed": 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, line := range output {
|
for _, line := range output {
|
||||||
line = strings.ToLower(line)
|
line = strings.ToLower(line)
|
||||||
for stage, progress := range stages {
|
for stage, progress := range stages {
|
||||||
@@ -1089,7 +1089,7 @@ func estimateProgress(output []string, service string) int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case "immich":
|
case "immich":
|
||||||
// Immich stages: database dump (50%), uploads backup (40%), upload to B2 (10%)
|
// Immich stages: database dump (50%), uploads backup (40%), upload to B2 (10%)
|
||||||
stages := map[string]int{
|
stages := map[string]int{
|
||||||
@@ -1099,7 +1099,7 @@ func estimateProgress(output []string, service string) int {
|
|||||||
"uploading to": 90,
|
"uploading to": 90,
|
||||||
"completed": 100,
|
"completed": 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, line := range output {
|
for _, line := range output {
|
||||||
line = strings.ToLower(line)
|
line = strings.ToLower(line)
|
||||||
for stage, progress := range stages {
|
for stage, progress := range stages {
|
||||||
@@ -1108,26 +1108,26 @@ func estimateProgress(output []string, service string) int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case "media":
|
case "media":
|
||||||
// Media services backup: each service adds progress
|
// Media services backup: each service adds progress
|
||||||
services := []string{"sonarr", "radarr", "prowlarr", "audiobookshelf", "tautulli", "sabnzbd", "jellyseerr"}
|
services := []string{"sonarr", "radarr", "prowlarr", "audiobookshelf", "tautulli", "sabnzbd", "jellyseerr"}
|
||||||
completed := 0
|
completed := 0
|
||||||
|
|
||||||
for _, service := range services {
|
for _, service := range services {
|
||||||
for _, line := range output {
|
for _, line := range output {
|
||||||
if strings.Contains(strings.ToLower(line), service) &&
|
if strings.Contains(strings.ToLower(line), service) &&
|
||||||
(strings.Contains(strings.ToLower(line), "success") ||
|
(strings.Contains(strings.ToLower(line), "success") ||
|
||||||
strings.Contains(strings.ToLower(line), "completed")) {
|
strings.Contains(strings.ToLower(line), "completed")) {
|
||||||
completed++
|
completed++
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (completed * 100) / len(services)
|
return (completed * 100) / len(services)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default progress estimation based on line count
|
// Default progress estimation based on line count
|
||||||
if len(output) < 10 {
|
if len(output) < 10 {
|
||||||
return 20
|
return 20
|
||||||
@@ -1136,7 +1136,7 @@ func estimateProgress(output []string, service string) int {
|
|||||||
} else if len(output) < 100 {
|
} else if len(output) < 100 {
|
||||||
return 80
|
return 80
|
||||||
}
|
}
|
||||||
|
|
||||||
return 90
|
return 90
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1248,11 +1248,11 @@ func createProgressBar(progress int) string {
|
|||||||
if progress > 100 {
|
if progress > 100 {
|
||||||
progress = 100
|
progress = 100
|
||||||
}
|
}
|
||||||
|
|
||||||
const barWidth = 30
|
const barWidth = 30
|
||||||
filled := (progress * barWidth) / 100
|
filled := (progress * barWidth) / 100
|
||||||
empty := barWidth - filled
|
empty := barWidth - filled
|
||||||
|
|
||||||
bar := strings.Repeat("█", filled) + strings.Repeat("░", empty)
|
bar := strings.Repeat("█", filled) + strings.Repeat("░", empty)
|
||||||
return fmt.Sprintf("[%s]", bar)
|
return fmt.Sprintf("[%s]", bar)
|
||||||
}
|
}
|
||||||
@@ -1263,7 +1263,7 @@ func (m Model) startProgressTicker(service string) tea.Cmd {
|
|||||||
// Check if backup is still running
|
// Check if backup is still running
|
||||||
if status, exists := m.backupStatus[service]; exists && status.Status == "running" {
|
if status, exists := m.backupStatus[service]; exists && status.Status == "running" {
|
||||||
elapsed := time.Since(status.StartTime)
|
elapsed := time.Since(status.StartTime)
|
||||||
|
|
||||||
// Estimate progress based on typical backup durations
|
// Estimate progress based on typical backup durations
|
||||||
var estimatedDuration time.Duration
|
var estimatedDuration time.Duration
|
||||||
switch service {
|
switch service {
|
||||||
@@ -1276,13 +1276,13 @@ func (m Model) startProgressTicker(service string) tea.Cmd {
|
|||||||
default:
|
default:
|
||||||
estimatedDuration = 5 * time.Minute
|
estimatedDuration = 5 * time.Minute
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate progress (cap at 95% until actual completion)
|
// Calculate progress (cap at 95% until actual completion)
|
||||||
progress := int((elapsed.Seconds() / estimatedDuration.Seconds()) * 95)
|
progress := int((elapsed.Seconds() / estimatedDuration.Seconds()) * 95)
|
||||||
if progress > 95 {
|
if progress > 95 {
|
||||||
progress = 95
|
progress = 95
|
||||||
}
|
}
|
||||||
|
|
||||||
return backupProgressMsg{
|
return backupProgressMsg{
|
||||||
service: service,
|
service: service,
|
||||||
progress: progress,
|
progress: progress,
|
||||||
|
|||||||
Reference in New Issue
Block a user