Skip to content

Commit dbf2119

Browse files
committed
🚸 reworked waiting animation logic
1 parent 7235ba4 commit dbf2119

File tree

5 files changed

+245
-40
lines changed

5 files changed

+245
-40
lines changed

docker-manager.sh

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,16 @@ route_operation() {
138138
source "$SCRIPT_DIR/operations/cleanup.sh"
139139
cleanup_multiple_containers "${CONTAINER_NAMES[@]}" "$FORCE"
140140
else
141-
local container_name=$(get_target_container)
142-
print_section "Cleaning up container: $container_name"
143-
source "$SCRIPT_DIR/operations/cleanup.sh"
144-
cleanup_container "$container_name" "$FORCE"
141+
# No container specified - check if we have a last container
142+
local last_container=$(get_last_container)
143+
if [[ -n "$last_container" ]]; then
144+
print_section "Cleaning up container: $last_container"
145+
source "$SCRIPT_DIR/operations/cleanup.sh"
146+
cleanup_container "$last_container" "$FORCE"
147+
else
148+
print_error "No containers to clean up"
149+
exit 1
150+
fi
145151
fi
146152
;;
147153
"nuke")
@@ -438,29 +444,7 @@ handle_restart() {
438444
fi
439445
}
440446

441-
# =============================================================================
442-
# FUNCTION: handle_cleanup
443-
# =============================================================================
444-
# Purpose: Handle the cleanup operation to remove containers and images
445-
# Inputs: None (uses global variables CONTAINER_NAME, FORCE)
446-
# Outputs: None
447-
# Side Effects:
448-
# - Sources and calls cleanup operation module
449-
# - Handles both single container cleanup and full system cleanup
450-
# Usage: Called by route_operation when operation is "cleanup"
451-
# =============================================================================
452-
handle_cleanup() {
453-
if [[ "$CONTAINER_NAME" == "--all" ]]; then
454-
print_section "Cleaning up all Docker resources"
455-
cleanup_docker "$FORCE"
456-
else
457-
local container_name=$(get_target_container)
458-
print_section "Cleaning up container: $container_name"
459-
460-
source "$SCRIPT_DIR/operations/cleanup.sh"
461-
cleanup_container "$container_name" "$FORCE"
462-
fi
463-
}
447+
464448

465449
# =============================================================================
466450
# FUNCTION: handle_status
@@ -506,10 +490,19 @@ handle_status() {
506490
# Usage: Called by route_operation when operation is "logs"
507491
# =============================================================================
508492
handle_logs() {
509-
local containers=($(get_target_containers))
510-
511-
if [[ ${#containers[@]} -eq 1 ]]; then
512-
local container_name="${containers[0]}"
493+
if [[ ${#CONTAINER_NAMES[@]} -eq 0 ]]; then
494+
# No container specified - check if we have a last container
495+
local last_container=$(get_last_container)
496+
if [[ -n "$last_container" ]]; then
497+
print_section "Logs for container: $last_container"
498+
source "$SCRIPT_DIR/operations/logs.sh"
499+
show_container_logs "$last_container"
500+
else
501+
print_error "No containers to show logs for"
502+
exit 1
503+
fi
504+
elif [[ ${#CONTAINER_NAMES[@]} -eq 1 ]]; then
505+
local container_name="${CONTAINER_NAMES[0]}"
513506
print_section "Logs for container: $container_name"
514507

515508
source "$SCRIPT_DIR/operations/logs.sh"
@@ -518,7 +511,7 @@ handle_logs() {
518511
print_section "Logs for multiple containers"
519512

520513
source "$SCRIPT_DIR/operations/logs.sh"
521-
show_multiple_containers_logs "${containers[@]}"
514+
show_multiple_containers_logs "${CONTAINER_NAMES[@]}"
522515
fi
523516
}
524517

docs/Notes.md

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,111 @@ Both operations now support the `--no-start` flag:
144144
- **Generate**: Uses `generate_from_yaml()` function that processes YAML files directly
145145
- **Install**: Uses `install_container()` function that calls `generate_from_yaml()` with stored YAML path
146146
- **State Management**: Both operations update the state file with container metadata
147-
- **--no-start Flag**: Both operations respect the flag to create containers without starting them
147+
- **--no-start Flag**: Both operations respect the flag to create containers without starting them
148+
149+
---
150+
151+
# Animation Display Issue Fix
152+
153+
## Problem Statement
154+
During container generation, extraneous characters (specifically "i") were appearing in the output after progress animations. The issue manifested as:
155+
156+
```
157+
...ℹ Waiting for container 'nginx-app-container' to be ready (timeout: 60s)
158+
```
159+
160+
Where the dots (`...`) from the animation were not being properly cleared before the next message was printed, causing visual artifacts.
161+
162+
## Root Cause Analysis
163+
The issue was caused by race conditions in the animation system:
164+
165+
1. **Line Clearing Logic**: The `printf "\r%*s\r"` commands were using dynamic width calculations that weren't working correctly
166+
2. **Timing Issues**: There was insufficient delay between stopping animations and printing the next message
167+
3. **Animation State**: The signal-based animation system wasn't properly clearing the terminal line before new content was displayed
168+
169+
## Solution Approach
170+
171+
### 1. Fixed Line Clearing Logic
172+
**Problem**: Dynamic width calculations in `printf "\r%*s\r" $((dots_count + 1)) ""` were unreliable
173+
**Solution**: Changed to fixed width of 80 characters: `printf "\r%*s\r" 80 ""`
174+
175+
**Files Modified**:
176+
- `lib/utils.sh`: Updated all animation functions to use consistent line clearing
177+
178+
### 2. Added Explicit Line Clearing
179+
**Problem**: Race conditions between animation stopping and next message printing
180+
**Solution**: Added explicit line clearing before showing waiting messages
181+
182+
**Files Modified**:
183+
- `lib/container_ops.sh`: Added `printf "\r%*s\r" 80 ""` before `print_info` calls
184+
185+
### 3. Added Timing Delays
186+
**Problem**: Insufficient time for animations to fully clear
187+
**Solution**: Added small delays (`sleep 0.1`) after stopping animations
188+
189+
**Files Modified**:
190+
- `lib/container_ops.sh`: Added delays after `stop_signal_animation` calls
191+
- `lib/utils.sh`: Enhanced `stop_signal_animation` with additional line clearing
192+
193+
### 4. Enhanced Animation Cleanup
194+
**Problem**: Animation processes weren't properly cleaning up terminal state
195+
**Solution**: Added explicit line clearing in animation cleanup functions
196+
197+
## Implementation Details
198+
199+
### Key Changes Made
200+
201+
1. **Consistent Line Clearing**:
202+
```bash
203+
# Before (problematic)
204+
printf "\r%*s\r" $((dots_count + 1)) ""
205+
206+
# After (fixed)
207+
printf "\r%*s\r" 80 ""
208+
```
209+
210+
2. **Explicit Pre-Message Clearing**:
211+
```bash
212+
# Ensure any previous animation is fully cleared
213+
printf "\r%*s\r" 80 ""
214+
print_info "Waiting for container '$container_name' to be ready..."
215+
```
216+
217+
3. **Animation Stop Delays**:
218+
```bash
219+
stop_signal_animation
220+
# Small delay to ensure animation is fully cleared
221+
sleep 0.1
222+
```
223+
224+
4. **Enhanced Cleanup**:
225+
```bash
226+
# Ensure line is cleared after animation stops
227+
printf "\r%*s\r" 80 ""
228+
```
229+
230+
## Testing Results
231+
232+
**Before Fix**:
233+
```
234+
...ℹ Waiting for container 'nginx-app-container' to be ready (timeout: 60s)
235+
```
236+
237+
**After Fix**:
238+
```
239+
ℹ Waiting for container 'nginx-app-container' to be ready (timeout: 60s)
240+
```
241+
242+
## Lessons Learned
243+
244+
1. **Terminal Animation Timing**: Even small race conditions can cause visual artifacts
245+
2. **Line Clearing Consistency**: Using fixed widths is more reliable than dynamic calculations
246+
3. **Animation State Management**: Proper cleanup is essential for multi-step processes
247+
4. **User Experience**: Clean output is crucial for professional tool appearance
248+
249+
## Future Considerations
250+
251+
- Consider implementing a more robust animation system with better state management
252+
- Add animation debugging capabilities for troubleshooting similar issues
253+
- Consider using a dedicated terminal library for complex animations
254+
- Implement animation queuing to prevent overlapping animations

lib/container_ops.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,9 @@ wait_for_container_ready() {
903903
local start_time=$(date +%s)
904904
local end_time=$((start_time + timeout))
905905

906+
# Ensure any previous animation is fully cleared
907+
printf "\r%*s\r" 80 ""
908+
906909
# Show waiting animation
907910
print_info "Waiting for container '$container_name' to be ready (timeout: ${timeout}s)"
908911

@@ -926,6 +929,8 @@ wait_for_container_ready() {
926929
# If healthy, stop animation and return success
927930
if [[ "$health_status" == "healthy" ]]; then
928931
stop_signal_animation
932+
# Small delay to ensure animation is fully cleared
933+
sleep 0.1
929934
log_operation_success "$operation" "$container_name" "Container is healthy and ready"
930935
return 0
931936
elif [[ "$health_status" == "unhealthy" ]]; then
@@ -948,6 +953,8 @@ wait_for_container_ready() {
948953

949954
# Timeout reached - stop animation
950955
stop_signal_animation
956+
# Small delay to ensure animation is fully cleared
957+
sleep 0.1
951958

952959
# After timeout, check if container is running and show appropriate message
953960
local is_running=$(container_is_running "$container_name" && echo "true" || echo "false")

lib/utils.sh

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ show_dots_animation() {
560560
done
561561

562562
# Clear the line
563-
printf "\r%*s\r" $(( ${#message} + max_dots + 1 )) ""
563+
printf "\r%*s\r" 80 ""
564564
}
565565

566566
# Show simple dots animation only
@@ -578,7 +578,7 @@ show_waiting_dots() {
578578
# Show one cycle of dots animation
579579
for ((i=0; i<=max_dots; i++)); do
580580
# Clear previous dots and show current state
581-
printf "\r%*s\r" $(( max_dots + 1 )) ""
581+
printf "\r%*s\r" 80 ""
582582
for ((j=0; j<i; j++)); do
583583
printf "."
584584
done
@@ -648,7 +648,7 @@ show_waiting_animation() {
648648
done
649649

650650
# Clear the line when done
651-
printf "\r%*s\r" $(( ${#message} + 10 )) ""
651+
printf "\r%*s\r" 80 ""
652652
}
653653

654654
# Show waiting animation with condition
@@ -681,7 +681,7 @@ show_waiting_animation_with_condition() {
681681
if [[ $((current_time - last_check_time)) -ge $check_interval ]]; then
682682
if eval "$condition_command" >/dev/null 2>&1; then
683683
# Clear the line when condition is met
684-
printf "\r%*s\r" $(( ${#message} + 10 )) ""
684+
printf "\r%*s\r" 80 ""
685685
return 0
686686
fi
687687
last_check_time=$current_time
@@ -697,7 +697,7 @@ show_waiting_animation_with_condition() {
697697
done
698698

699699
# Clear the line when timeout occurs
700-
printf "\r%*s\r" $(( ${#message} + 10 )) ""
700+
printf "\r%*s\r" 80 ""
701701
return 1
702702
}
703703

@@ -744,7 +744,7 @@ start_signal_animation() {
744744
# Start animation in background process
745745
(
746746
# Set up signal handler for this process
747-
trap 'rm -f "$signal_file"; printf "\r%*s\r" $((dots_count + 1)) ""; exit 0' SIGUSR1 EXIT
747+
trap 'rm -f "$signal_file"; printf "\r%*s\r" 80 ""; exit 0' SIGUSR1 EXIT
748748

749749
# Run animation until signal file is created or signal received
750750
while [[ ! -f "$signal_file" ]]; do
@@ -753,7 +753,7 @@ start_signal_animation() {
753753

754754
# Clean up and exit
755755
rm -f "$signal_file"
756-
printf "\r%*s\r" $((dots_count + 1)) ""
756+
printf "\r%*s\r" 80 ""
757757
) &
758758

759759
_ANIMATION_PID=$!
@@ -810,6 +810,9 @@ stop_signal_animation() {
810810
_ANIMATION_SIGNAL_RECEIVED=false
811811
_ANIMATION_SIGNAL_FILE=""
812812

813+
# Ensure line is cleared after animation stops
814+
printf "\r%*s\r" 80 ""
815+
813816
log_debug "ANIMATION" "" "Signal-based animation stopped"
814817
fi
815818
}
@@ -1296,4 +1299,77 @@ send_notification() {
12961299
fi
12971300
}
12981301

1302+
# =============================================================================
1303+
# PROGRESS INDICATORS FOR CONTAINER GENERATION
1304+
# =============================================================================
1305+
1306+
# Show generation progress with animation
1307+
# Displays animated progress messages for container generation steps
1308+
# Provides visual feedback during the generation process
1309+
#
1310+
# Input:
1311+
# $1 - step: The current step (1-4)
1312+
# $2 - yaml_file: The YAML file being processed
1313+
# $3 - container_name: The container name being generated
1314+
# Output: Animated progress message to stdout
1315+
# Example: show_generation_progress 1 "docker-compose.yml" "nginx"
1316+
show_generation_progress() {
1317+
local step="$1"
1318+
local yaml_file="$2"
1319+
local container_name="$3"
1320+
1321+
case "$step" in
1322+
1)
1323+
printf "\r%s" "📋 Extracting config from $(basename "$yaml_file")"
1324+
show_waiting_dots 3
1325+
;;
1326+
2)
1327+
printf "\r%s" "🔧 Generating docker-compose file"
1328+
show_waiting_dots 3
1329+
;;
1330+
3)
1331+
printf "\r%s" "🐳 Creating container '$container_name'"
1332+
show_waiting_dots 3
1333+
;;
1334+
4)
1335+
printf "\r%s" "✅ Finalizing container setup"
1336+
show_waiting_dots 3
1337+
;;
1338+
esac
1339+
}
1340+
1341+
# Show generation step completion
1342+
# Displays a completion message for each generation step
1343+
# Clears the progress line and shows completion status
1344+
#
1345+
# Input:
1346+
# $1 - step: The completed step (1-4)
1347+
# $2 - yaml_file: The YAML file being processed
1348+
# $3 - container_name: The container name being generated
1349+
# Output: Completion message to stdout
1350+
# Example: show_generation_step_complete 1 "docker-compose.yml" "nginx"
1351+
show_generation_step_complete() {
1352+
local step="$1"
1353+
local yaml_file="$2"
1354+
local container_name="$3"
1355+
1356+
# Clear the progress line
1357+
printf "\r%*s\r" 80 ""
1358+
1359+
case "$step" in
1360+
1)
1361+
print_success "Config extracted from $(basename "$yaml_file")"
1362+
;;
1363+
2)
1364+
print_success "Docker-compose file generated"
1365+
;;
1366+
3)
1367+
print_success "Container '$container_name' created"
1368+
;;
1369+
4)
1370+
print_success "Container setup completed"
1371+
;;
1372+
esac
1373+
}
1374+
12991375

0 commit comments

Comments
 (0)