1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-10 17:14:17 +00:00

The results are more uniform

This commit is contained in:
Tw93
2025-10-11 15:02:15 +08:00
parent 8dc8d6c063
commit 3b33c5a4a8
6 changed files with 181 additions and 101 deletions

View File

@@ -175,37 +175,47 @@ batch_uninstall_applications() {
done
# Summary
local freed_display=$(bytes_to_human "$((total_size_freed * 1024))")
local bar="================================================================================"
echo "$bar"
local freed_display
freed_display=$(bytes_to_human "$((total_size_freed * 1024))")
local summary_status="success"
local -a summary_details=()
if [[ $success_count -gt 0 ]]; then
local success_list="${success_items[*]}"
echo -e "Removed: ${GREEN}${success_list}${NC} | Freed: ${GREEN}${freed_display}${NC}"
summary_details+=("Removed: ${GREEN}${success_list}${NC}")
summary_details+=("Freed space: ${GREEN}${freed_display}${NC}")
fi
if [[ $failed_count -gt 0 ]]; then
summary_status="warn"
local failed_names=()
local reason_summary=""
for item in "${failed_items[@]}"; do
local name=${item%%:*}
failed_names+=("$name")
done
local failed_list="${failed_names[*]}"
# Determine primary reason
local reason_summary="could not be removed"
if [[ $failed_count -eq 1 ]]; then
local first_reason=${failed_items[0]#*:}
case "$first_reason" in
still*running*) reason_summary="still running" ;;
still*running*) reason_summary="is still running" ;;
remove*failed*) reason_summary="could not be removed" ;;
permission*) reason_summary="permission denied" ;;
*) reason_summary="$first_reason" ;;
esac
echo -e "Failed: ${RED}${failed_list}${NC} ${reason_summary}"
else
echo -e "Failed: ${RED}${failed_list}${NC} could not be removed"
fi
summary_details+=("Failed: ${RED}${failed_list}${NC} ${reason_summary}")
fi
echo "$bar"
if [[ $success_count -eq 0 && $failed_count -eq 0 ]]; then
summary_status="info"
summary_details+=("No applications were uninstalled.")
fi
print_summary_block "$summary_status" "Uninstall complete" "${summary_details[@]}"
if [[ ${#dock_cleanup_paths[@]} -gt 0 ]]; then
remove_apps_from_dock "${dock_cleanup_paths[@]}"

View File

@@ -22,7 +22,7 @@ readonly NC="${ESC}[0m"
# Icon definitions
readonly ICON_CONFIRM="◎" # Confirm operation
readonly ICON_ADMIN="" # Admin permission
readonly ICON_ADMIN="" # Admin permission
readonly ICON_SUCCESS="✓" # Success
readonly ICON_ERROR="✗" # Error
readonly ICON_EMPTY="○" # Empty state
@@ -116,6 +116,39 @@ icon_menu() {
echo -e "${BLUE}${ICON_MENU} ${num}. ${text}${NC}"
}
# Consistent summary blocks for command results
print_summary_block() {
local status="info"
local heading=""
if [[ $# -gt 0 ]]; then
status="$1"
shift
fi
if [[ $# -gt 0 ]]; then
heading="$1"
shift
fi
local -a details=("$@")
local divider="======================================================================"
local color="$BLUE"
local indent=" "
echo "$divider"
if [[ -n "$heading" ]]; then
echo -e "${BLUE}${heading}${NC}"
fi
for detail in "${details[@]}"; do
[[ -z "$detail" ]] && continue
echo -e "${detail}"
done
echo "$divider"
}
# System detection
detect_architecture() {
if [[ "$(uname -m)" == "arm64" ]]; then
@@ -343,7 +376,7 @@ request_sudo_access() {
# If Touch ID is supported and not forced to use password
if [[ "$force_password" != "true" ]] && check_touchid_support; then
echo -e "${BLUE}${ICON_ADMIN}${NC} ${prompt_msg} ${GRAY}(Touch ID or password)${NC}"
echo -e "${GRAY}${ICON_ADMIN}${NC} ${GRAY}${prompt_msg} (Touch ID or password)${NC}"
if sudo -v 2>/dev/null; then
return 0
else
@@ -351,8 +384,8 @@ request_sudo_access() {
fi
else
# Traditional password method
echo -e "${BLUE}${ICON_ADMIN}${NC} ${prompt_msg}"
echo -ne "${BLUE}${ICON_MENU}${NC} Password: "
echo -e "${GRAY}${ICON_ADMIN}${NC} ${GRAY}${prompt_msg}${NC}"
echo -ne "${GRAY}${ICON_MENU}${NC} Password: "
read -s password
echo ""
if [[ -n "$password" ]] && echo "$password" | sudo -S true 2>/dev/null; then

View File

@@ -25,9 +25,8 @@ paginated_multi_select() {
local total_items=${#items[@]}
local items_per_page=15
local total_pages=$(( (total_items + items_per_page - 1) / items_per_page ))
local current_page=0
local cursor_pos=0
local top_index=0
local -a selected=()
# Initialize selection array
@@ -113,30 +112,48 @@ paginated_multi_select() {
# Clear each line as we go instead of clearing entire screen
local clear_line="\r\033[2K"
# Header - compute underline length without external seq dependency
local title_clean="${title//[^[:print:]]/}"
local underline_len=${#title_clean}
[[ $underline_len -lt 10 ]] && underline_len=10
# Build underline robustly (no seq); printf width then translate spaces to '='
local underline
underline=$(printf '%*s' "$underline_len" '' | tr ' ' '=')
printf "${clear_line}${PURPLE}%s${NC}\n" "$title" >&2
printf "${clear_line}%s\n" "$underline" >&2
# Status
# Count selections for header display
local selected_count=0
for ((i = 0; i < total_items; i++)); do
[[ ${selected[i]} == true ]] && ((selected_count++))
done
printf "${clear_line}Page %d/%d │ Total: %d │ Selected: %d\n\n" \
$((current_page + 1)) $total_pages $total_items $selected_count >&2
# Items for current page
local start_idx=$((current_page * items_per_page))
local end_idx=$((start_idx + items_per_page - 1))
# Header
printf "${clear_line}${PURPLE}%s${NC} ${GRAY}%d/%d selected${NC}\n" "${title}" "$selected_count" "$total_items" >&2
if [[ $total_items -eq 0 ]]; then
printf "${clear_line}${GRAY}No items available${NC}\n" >&2
printf "${clear_line}\n" >&2
printf "${clear_line}${GRAY}Q/ESC${NC} Quit\n" >&2
printf "${clear_line}" >&2
return
fi
if [[ $top_index -gt $((total_items - 1)) ]]; then
if [[ $total_items -gt $items_per_page ]]; then
top_index=$((total_items - items_per_page))
else
top_index=0
fi
fi
local visible_count=$((total_items - top_index))
[[ $visible_count -gt $items_per_page ]] && visible_count=$items_per_page
[[ $visible_count -le 0 ]] && visible_count=1
if [[ $cursor_pos -ge $visible_count ]]; then
cursor_pos=$((visible_count - 1))
[[ $cursor_pos -lt 0 ]] && cursor_pos=0
fi
printf "${clear_line}\n" >&2
# Items for current window
local start_idx=$top_index
local end_idx=$((top_index + items_per_page - 1))
[[ $end_idx -ge $total_items ]] && end_idx=$((total_items - 1))
for ((i = start_idx; i <= end_idx; i++)); do
[[ $i -lt 0 ]] && continue
local is_current=false
[[ $((i - start_idx)) -eq $cursor_pos ]] && is_current=true
render_item $i $is_current
@@ -144,13 +161,14 @@ paginated_multi_select() {
# Fill empty slots to clear previous content
local items_shown=$((end_idx - start_idx + 1))
[[ $items_shown -lt 0 ]] && items_shown=0
for ((i = items_shown; i < items_per_page; i++)); do
printf "${clear_line}\n" >&2
done
# Clear any remaining lines at bottom
printf "${clear_line}\n" >&2
printf "${clear_line}${GRAY}↑/↓${NC} Navigate ${GRAY}|${NC} ${GRAY}Space${NC} Select ${GRAY}|${NC} ${GRAY}Enter${NC} Confirm ${GRAY}|${NC} ${GRAY}Q/ESC${NC} Quit ${GRAY}|${NC} ○ off ● on\n" >&2
printf "${clear_line}${GRAY}↑/↓${NC} Navigate ${GRAY}|${NC} ${GRAY}Space${NC} Select ${GRAY}|${NC} ${GRAY}Enter${NC} Confirm ${GRAY}|${NC} ${GRAY}Q/ESC${NC} Quit\n" >&2
# Clear one more line to ensure no artifacts
printf "${clear_line}" >&2
@@ -184,31 +202,38 @@ EOF
return 1
;;
"UP")
if [[ $cursor_pos -gt 0 ]]; then
if [[ $total_items -eq 0 ]]; then
:
elif [[ $cursor_pos -gt 0 ]]; then
((cursor_pos--))
elif [[ $current_page -gt 0 ]]; then
((current_page--))
# Calculate cursor position for new page
local start_idx=$((current_page * items_per_page))
local items_on_page=$((total_items - start_idx))
[[ $items_on_page -gt $items_per_page ]] && items_on_page=$items_per_page
cursor_pos=$((items_on_page - 1))
elif [[ $top_index -gt 0 ]]; then
((top_index--))
fi
;;
"DOWN")
local start_idx=$((current_page * items_per_page))
local items_on_page=$((total_items - start_idx))
[[ $items_on_page -gt $items_per_page ]] && items_on_page=$items_per_page
if [[ $total_items -eq 0 ]]; then
:
else
local absolute_index=$((top_index + cursor_pos))
if [[ $absolute_index -lt $((total_items - 1)) ]]; then
local visible_count=$((total_items - top_index))
[[ $visible_count -gt $items_per_page ]] && visible_count=$items_per_page
if [[ $cursor_pos -lt $((items_on_page - 1)) ]]; then
((cursor_pos++))
elif [[ $current_page -lt $((total_pages - 1)) ]]; then
((current_page++))
cursor_pos=0
if [[ $cursor_pos -lt $((visible_count - 1)) ]]; then
((cursor_pos++))
elif [[ $((top_index + visible_count)) -lt $total_items ]]; then
((top_index++))
visible_count=$((total_items - top_index))
[[ $visible_count -gt $items_per_page ]] && visible_count=$items_per_page
if [[ $cursor_pos -ge $visible_count ]]; then
cursor_pos=$((visible_count - 1))
fi
fi
fi
fi
;;
"SPACE")
local idx=$((current_page * items_per_page + cursor_pos))
local idx=$((top_index + cursor_pos))
if [[ $idx -lt $total_items ]]; then
if [[ ${selected[idx]} == true ]]; then
selected[idx]=false

View File

@@ -280,9 +280,9 @@ manage_whitelist_categories() {
save_whitelist_patterns
fi
echo ""
echo -e "${GREEN}${NC} Protected ${#selected_patterns[@]} cache(s)"
echo -e "${GRAY}Config: ${WHITELIST_CONFIG}${NC}"
print_summary_block "success" \
"Protected ${#selected_patterns[@]} cache(s)" \
"Saved to ${WHITELIST_CONFIG}"
}