mirror of
https://github.com/tw93/Mole.git
synced 2026-02-05 18:28:53 +00:00
150 lines
5.1 KiB
Bash
Executable File
150 lines
5.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# App selection functionality
|
|
|
|
set -euo pipefail
|
|
|
|
# Note: get_display_width() is now defined in lib/core/ui.sh
|
|
|
|
# Format app info for display
|
|
format_app_display() {
|
|
local display_name="$1" size="$2" last_used="$3"
|
|
|
|
# Use common function from ui.sh to format last used time
|
|
local compact_last_used
|
|
compact_last_used=$(format_last_used_summary "$last_used")
|
|
|
|
# Format size
|
|
local size_str="Unknown"
|
|
[[ "$size" != "0" && "$size" != "" && "$size" != "Unknown" ]] && size_str="$size"
|
|
|
|
# Calculate available width for app name based on terminal width
|
|
# use passed width or calculate it (but calculation is slow in loops)
|
|
local terminal_width="${4:-$(tput cols 2> /dev/null || echo 80)}"
|
|
local fixed_width=28
|
|
local available_width=$((terminal_width - fixed_width))
|
|
|
|
# Set reasonable bounds for name width: 24-35 display width
|
|
[[ $available_width -lt 24 ]] && available_width=24
|
|
[[ $available_width -gt 35 ]] && available_width=35
|
|
|
|
# Truncate long names if needed (based on display width, not char count)
|
|
local truncated_name
|
|
truncated_name=$(truncate_by_display_width "$display_name" "$available_width")
|
|
|
|
# Get actual display width after truncation
|
|
local current_display_width
|
|
current_display_width=$(get_display_width "$truncated_name")
|
|
|
|
# Calculate padding needed
|
|
# Formula: char_count + (available_width - display_width) = padding to add
|
|
local char_count=${#truncated_name}
|
|
local padding_needed=$((available_width - current_display_width))
|
|
local printf_width=$((char_count + padding_needed))
|
|
|
|
# Use dynamic column width with corrected padding
|
|
printf "%-*s %9s | %s" "$printf_width" "$truncated_name" "$size_str" "$compact_last_used"
|
|
}
|
|
|
|
# Global variable to store selection result (bash 3.2 compatible)
|
|
MOLE_SELECTION_RESULT=""
|
|
|
|
# Main app selection function
|
|
# shellcheck disable=SC2154 # apps_data is set by caller
|
|
select_apps_for_uninstall() {
|
|
if [[ ${#apps_data[@]} -eq 0 ]]; then
|
|
log_warning "No applications available for uninstallation"
|
|
return 1
|
|
fi
|
|
|
|
# Build menu options
|
|
# Show loading for large lists (formatting can be slow due to width calculations)
|
|
local app_count=${#apps_data[@]}
|
|
local terminal_width=$(tput cols 2> /dev/null || echo 80)
|
|
if [[ $app_count -gt 100 ]]; then
|
|
if [[ -t 2 ]]; then
|
|
printf "\rPreparing %d applications... " "$app_count" >&2
|
|
fi
|
|
fi
|
|
|
|
local -a menu_options=()
|
|
# Prepare metadata (comma-separated) for sorting/filtering inside the menu
|
|
local epochs_csv=""
|
|
local sizekb_csv=""
|
|
local idx=0
|
|
for app_data in "${apps_data[@]}"; do
|
|
# Keep extended field 7 (size_kb) if present
|
|
IFS='|' read -r epoch _ display_name _ size last_used size_kb <<< "$app_data"
|
|
menu_options+=("$(format_app_display "$display_name" "$size" "$last_used" "$terminal_width")")
|
|
# Build csv lists (avoid trailing commas)
|
|
if [[ $idx -eq 0 ]]; then
|
|
epochs_csv="${epoch:-0}"
|
|
sizekb_csv="${size_kb:-0}"
|
|
else
|
|
epochs_csv+=",${epoch:-0}"
|
|
sizekb_csv+=",${size_kb:-0}"
|
|
fi
|
|
((idx++))
|
|
done
|
|
|
|
# Clear loading message
|
|
if [[ $app_count -gt 100 ]]; then
|
|
if [[ -t 2 ]]; then
|
|
printf "\r\033[K" >&2
|
|
fi
|
|
fi
|
|
|
|
# Expose metadata for the paginated menu (optional inputs)
|
|
# - MOLE_MENU_META_EPOCHS: numeric last_used_epoch per item
|
|
# - MOLE_MENU_META_SIZEKB: numeric size in KB per item
|
|
# The menu will gracefully fallback if these are unset or malformed.
|
|
export MOLE_MENU_META_EPOCHS="$epochs_csv"
|
|
export MOLE_MENU_META_SIZEKB="$sizekb_csv"
|
|
# Optional: allow default sort override via env (date|name|size)
|
|
# export MOLE_MENU_SORT_DEFAULT="${MOLE_MENU_SORT_DEFAULT:-date}"
|
|
|
|
# Use paginated menu - result will be stored in MOLE_SELECTION_RESULT
|
|
# Note: paginated_multi_select enters alternate screen and handles clearing
|
|
MOLE_SELECTION_RESULT=""
|
|
paginated_multi_select "Select Apps to Remove" "${menu_options[@]}"
|
|
local exit_code=$?
|
|
|
|
# Clean env leakage for safety
|
|
unset MOLE_MENU_META_EPOCHS MOLE_MENU_META_SIZEKB
|
|
# leave MOLE_MENU_SORT_DEFAULT untouched if user set it globally
|
|
|
|
# Refresh signal handling
|
|
if [[ $exit_code -eq 10 ]]; then
|
|
return 10
|
|
fi
|
|
|
|
if [[ $exit_code -ne 0 ]]; then
|
|
echo "Cancelled"
|
|
return 1
|
|
fi
|
|
|
|
if [[ -z "$MOLE_SELECTION_RESULT" ]]; then
|
|
echo "No apps selected"
|
|
return 1
|
|
fi
|
|
|
|
# Build selected apps array (global variable in bin/uninstall.sh)
|
|
selected_apps=()
|
|
|
|
# Parse indices and build selected apps array
|
|
IFS=',' read -r -a indices_array <<< "$MOLE_SELECTION_RESULT"
|
|
|
|
for idx in "${indices_array[@]}"; do
|
|
if [[ "$idx" =~ ^[0-9]+$ ]] && [[ $idx -ge 0 ]] && [[ $idx -lt ${#apps_data[@]} ]]; then
|
|
selected_apps+=("${apps_data[idx]}")
|
|
fi
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
# Export function for external use
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
echo "This is a library file. Source it from other scripts." >&2
|
|
exit 1
|
|
fi
|