1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-04 15:39:42 +00:00

🎨 Uninstalling and cleaning is a cleaner experience

This commit is contained in:
Tw93
2025-10-04 17:59:12 +08:00
parent a3c3975f5f
commit a830123ac4
5 changed files with 86 additions and 71 deletions

View File

@@ -257,65 +257,66 @@ safe_clean() {
}
start_cleanup() {
clear
echo ""
echo -e "${PURPLE}🧹 Clean Your Mac${NC}"
echo ""
echo "Mole will remove app caches, browser data, developer tools, and temporary files."
echo ""
if [[ "$DRY_RUN" != "true" && -t 0 ]]; then
echo -e "${BLUE}Tip:${NC} Want a preview first? Run 'mole clean --dry-run'."
echo ""
echo -e "${BLUE}Tip:${NC} Want a preview first? Run 'mole clean --dry-run'."
fi
if [[ "$DRY_RUN" == "true" ]]; then
echo ""
echo -e "${YELLOW}🧪 Dry Run mode:${NC} showing what would be removed (no deletions)."
echo ""
SYSTEM_CLEAN=false
return
fi
local password=""
if [[ -t 0 ]]; then
echo "Enter admin password for system-level cleanup (or press Enter to skip):"
echo -n "> "
echo ""
echo "System-level cleanup removes system caches and temp files, optional."
echo -en "${BLUE}Enter admin password to enable, or press Enter to skip: ${NC}"
read -s password
echo ""
else
password=""
echo ""
echo -e "${BLUE}${NC} Running in non-interactive mode"
echo " • System-level cleanup will be skipped (requires password)"
echo " • User-level cleanup will proceed automatically"
echo ""
fi
if [[ -n "$password" ]] && echo "$password" | sudo -S true 2>/dev/null; then
SYSTEM_CLEAN=true
# Start sudo keepalive with error handling and shorter intervals
(
local retry_count=0
while true; do
if ! sudo -n true 2>/dev/null; then
((retry_count++))
if [[ $retry_count -ge 3 ]]; then
log_warning "Sudo keepalive failed, system-level cleanup may be interrupted" >&2
exit 1
if [[ -n "$password" ]] && echo "$password" | sudo -S true 2>/dev/null; then
SYSTEM_CLEAN=true
# Start sudo keepalive with error handling
(
local retry_count=0
while true; do
if ! sudo -n true 2>/dev/null; then
((retry_count++))
if [[ $retry_count -ge 3 ]]; then
exit 1
fi
sleep 5
continue
fi
sleep 5
continue
fi
retry_count=0
sleep 30
kill -0 "$$" 2>/dev/null || exit
done
) 2>/dev/null &
SUDO_KEEPALIVE_PID=$!
log_info "Starting comprehensive cleanup with admin privileges..."
retry_count=0
sleep 30
kill -0 "$$" 2>/dev/null || exit
done
) 2>/dev/null &
SUDO_KEEPALIVE_PID=$!
else
SYSTEM_CLEAN=false
if [[ -n "$password" ]]; then
echo ""
echo -e "${YELLOW}⚠️ Invalid password, continuing with user-level cleanup${NC}"
fi
fi
else
SYSTEM_CLEAN=false
log_info "Starting user-level cleanup..."
if [[ -n "$password" ]]; then
echo -e "${YELLOW}⚠️ Invalid password, continuing with user-level cleanup${NC}"
fi
echo ""
echo -e "${BLUE}${NC} Running in non-interactive mode"
echo " • System-level cleanup skipped (requires interaction)"
echo " • User-level cleanup will proceed automatically"
echo ""
fi
}

View File

@@ -19,29 +19,29 @@ source "$SCRIPT_DIR/../lib/batch_uninstall.sh"
# Help information
show_help() {
echo "App Uninstaller"
echo "==============="
echo "Usage: mole uninstall"
echo ""
echo "Uninstall applications and clean their data completely."
echo "Interactive application uninstaller - Remove apps completely"
echo ""
echo "Controls:"
echo " ↑/↓ Navigate"
echo " SPACE Select/deselect"
echo " ENTER Confirm"
echo " Q Quit"
echo ""
echo "Usage:"
echo " ./uninstall.sh Launch interactive uninstaller"
echo " ./uninstall.sh --help Show this help message"
echo "Keyboard Controls:"
echo " ↑/↓ Navigate items"
echo " Space Select/deselect"
echo " Enter Confirm and uninstall"
echo " Q / ESC Quit"
echo ""
echo "What gets cleaned:"
echo " • Application bundle"
echo " • Application Support data"
echo " • Application Support data (12+ locations)"
echo " • Cache files"
echo " • Preference files"
echo " • Log files"
echo " • Saved application state"
echo " • Container data (sandboxed apps)"
echo " • WebKit storage, HTTP storage, cookies"
echo " • Extensions, plugins, services"
echo ""
echo "Examples:"
echo " mole uninstall Launch interactive uninstaller"
echo ""
}
@@ -116,11 +116,13 @@ scan_applications() {
local temp_file=$(mktemp)
echo -n "Scanning... " >&2
# Pre-cache current epoch to avoid repeated calls
local current_epoch=$(date "+%s")
# Spinner for scanning feedback
local spinner_chars="⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
local spinner_idx=0
# First pass: quickly collect all valid app paths and bundle IDs
local -a app_data_tuples=()
while IFS= read -r -d '' app_path; do
@@ -279,8 +281,10 @@ scan_applications() {
process_app_metadata "$app_data_tuple" "$temp_file" "$current_epoch" &
pids+=($!)
# Update progress
echo -ne "\rScanning... $app_count/$total_apps" >&2
# Update progress with spinner
local spinner_char="${spinner_chars:$((spinner_idx % 10)):1}"
echo -ne "\r🗑 ${spinner_char} Scanning... $app_count/$total_apps" >&2
((spinner_idx++))
# Wait if we've hit max parallel limit
if (( ${#pids[@]} >= max_parallel )); then
@@ -294,7 +298,8 @@ scan_applications() {
wait "$pid" 2>/dev/null
done
echo -e "\rFound $app_count applications " >&2
echo -e "\r🗑️ ✓ Found $app_count applications " >&2
echo "" >&2
# Check if we found any applications
if [[ ! -s "$temp_file" ]]; then

View File

@@ -37,17 +37,11 @@ select_apps_for_uninstall() {
menu_options+=("$(format_app_display "$display_name" "$size" "$last_used")")
done
echo ""
echo "🗑️ App Uninstaller"
echo ""
echo "Mole will uninstall selected apps and clean all their related files."
echo ""
echo "Found ${#apps_data[@]} apps. Select apps to remove:"
echo ""
# Use paginated menu - result will be stored in MOLE_SELECTION_RESULT
MOLE_SELECTION_RESULT=""
paginated_multi_select "Select Apps to Remove" "${menu_options[@]}"
paginated_multi_select "🗑️ Select Apps to Remove" "${menu_options[@]}"
local exit_code=$?
if [[ $exit_code -ne 0 ]]; then

View File

@@ -20,8 +20,18 @@ batch_uninstall_applications() {
local -a app_details=()
echo ""
echo -e "${BLUE}📋 Analyzing selected applications...${NC}"
# Show analyzing message with spinner
local spinner_chars="⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
local spinner_idx=0
local analyzed=0
for selected_app in "${selected_apps[@]}"; do
# Update spinner
local spinner_char="${spinner_chars:$((spinner_idx % 10)):1}"
((analyzed++))
echo -ne "\r🗑 ${spinner_char} Analyzing... $analyzed/${#selected_apps[@]}" >&2
((spinner_idx++))
IFS='|' read -r epoch app_path app_name bundle_id size last_used <<< "$selected_app"
# Check if app is running
@@ -47,6 +57,9 @@ batch_uninstall_applications() {
app_details+=("$app_name|$app_path|$bundle_id|$total_kb|$encoded_files")
done
# Clear spinner line
echo -ne "\r\033[K" >&2
# Format size display
if [[ $total_estimated_size -gt 1048576 ]]; then
local size_display=$(echo "$total_estimated_size" | awk '{printf "%.2fGB", $1/1024/1024}')

View File

@@ -63,8 +63,12 @@ paginated_multi_select() {
draw_menu() {
printf "\033[H\033[J" >&2 # Clear screen and move to top
# Header
printf "%s\n%s\n" "$title" "$(printf '=%.0s' $(seq 1 ${#title}))" >&2
# Header - strip emoji for length calculation
local title_clean="${title//[^[:print:]]/}"
local title_len_approx=$(( ${#title_clean} - 4 )) # Rough adjustment for emoji
[[ $title_len_approx -lt 10 ]] && title_len_approx=10
printf "${PURPLE}%s${NC}\n%s\n" "$title" "$(printf '=%.0s' $(seq 1 $title_len_approx))" >&2
# Status
local selected_count=0
@@ -92,7 +96,7 @@ paginated_multi_select() {
done
print_line ""
print_line "↑↓: Navigate | Space: Select | Enter: Confirm | Q: Exit"
print_line "${GRAY}↑/↓${NC} Navigate ${GRAY}|${NC} ${GRAY}Space${NC} Select ${GRAY}|${NC} ${GRAY}Enter${NC} Confirm ${GRAY}|${NC} ${GRAY}Q/ESC${NC} Quit"
}
# Show help screen
@@ -105,9 +109,7 @@ Help - Navigation Controls
↑ / ↓ Navigate up/down
Space Select/deselect item
Enter Confirm selection
A Select all
N Deselect all
Q Exit
Q / ESC Exit
Press any key to continue...
EOF