mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 18:34:46 +00:00
Keyboard optimization processing and log performance optimization
This commit is contained in:
@@ -144,7 +144,7 @@ show_menu() {
|
|||||||
if is_touchid_configured; then
|
if is_touchid_configured; then
|
||||||
echo -ne "${PURPLE}☛${NC} Press ${GREEN}Enter${NC} to disable, ${GRAY}Q${NC} to quit: "
|
echo -ne "${PURPLE}☛${NC} Press ${GREEN}Enter${NC} to disable, ${GRAY}Q${NC} to quit: "
|
||||||
IFS= read -r -s -n1 key || key=""
|
IFS= read -r -s -n1 key || key=""
|
||||||
drain_pending_input # Clean up any escape sequence remnants
|
drain_pending_input # Clean up any escape sequence remnants
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
case "$key" in
|
case "$key" in
|
||||||
@@ -163,7 +163,7 @@ show_menu() {
|
|||||||
else
|
else
|
||||||
echo -ne "${PURPLE}☛${NC} Press ${GREEN}Enter${NC} to enable, ${GRAY}Q${NC} to quit: "
|
echo -ne "${PURPLE}☛${NC} Press ${GREEN}Enter${NC} to enable, ${GRAY}Q${NC} to quit: "
|
||||||
IFS= read -r -s -n1 key || key=""
|
IFS= read -r -s -n1 key || key=""
|
||||||
drain_pending_input # Clean up any escape sequence remnants
|
drain_pending_input # Clean up any escape sequence remnants
|
||||||
|
|
||||||
case "$key" in
|
case "$key" in
|
||||||
$'\e') # ESC
|
$'\e') # ESC
|
||||||
|
|||||||
104
lib/common.sh
104
lib/common.sh
@@ -120,8 +120,12 @@ readonly LOG_MAX_SIZE_DEFAULT=1048576 # 1MB
|
|||||||
# Ensure log directory exists
|
# Ensure log directory exists
|
||||||
mkdir -p "$(dirname "$LOG_FILE")" 2> /dev/null || true
|
mkdir -p "$(dirname "$LOG_FILE")" 2> /dev/null || true
|
||||||
|
|
||||||
# Log file maintenance (must be defined before logging functions)
|
# Log rotation check (called once at startup, not per log entry)
|
||||||
rotate_log() {
|
rotate_log_once() {
|
||||||
|
# Skip if already checked this session
|
||||||
|
[[ -n "${MOLE_LOG_ROTATED:-}" ]] && return 0
|
||||||
|
export MOLE_LOG_ROTATED=1
|
||||||
|
|
||||||
local max_size="${MOLE_MAX_LOG_SIZE:-$LOG_MAX_SIZE_DEFAULT}"
|
local max_size="${MOLE_MAX_LOG_SIZE:-$LOG_MAX_SIZE_DEFAULT}"
|
||||||
if [[ -f "$LOG_FILE" ]] && [[ $(stat -f%z "$LOG_FILE" 2> /dev/null || echo 0) -gt "$max_size" ]]; then
|
if [[ -f "$LOG_FILE" ]] && [[ $(stat -f%z "$LOG_FILE" 2> /dev/null || echo 0) -gt "$max_size" ]]; then
|
||||||
mv "$LOG_FILE" "${LOG_FILE}.old" 2> /dev/null || true
|
mv "$LOG_FILE" "${LOG_FILE}.old" 2> /dev/null || true
|
||||||
@@ -129,37 +133,35 @@ rotate_log() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Enhanced logging functions with file logging support
|
# Simplified logging functions (no per-call rotation check)
|
||||||
log_info() {
|
log_info() {
|
||||||
rotate_log
|
|
||||||
echo -e "${BLUE}$1${NC}"
|
echo -e "${BLUE}$1${NC}"
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO: $1" >> "$LOG_FILE" 2> /dev/null || true
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO: $1" >> "$LOG_FILE" 2> /dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
log_success() {
|
log_success() {
|
||||||
rotate_log
|
|
||||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} $1"
|
echo -e " ${GREEN}${ICON_SUCCESS}${NC} $1"
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS: $1" >> "$LOG_FILE" 2> /dev/null || true
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS: $1" >> "$LOG_FILE" 2> /dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
log_warning() {
|
log_warning() {
|
||||||
rotate_log
|
|
||||||
echo -e "${YELLOW}$1${NC}"
|
echo -e "${YELLOW}$1${NC}"
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: $1" >> "$LOG_FILE" 2> /dev/null || true
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: $1" >> "$LOG_FILE" 2> /dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
log_error() {
|
log_error() {
|
||||||
rotate_log
|
|
||||||
echo -e "${RED}${ICON_ERROR}${NC} $1" >&2
|
echo -e "${RED}${ICON_ERROR}${NC} $1" >&2
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >> "$LOG_FILE" 2> /dev/null || true
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >> "$LOG_FILE" 2> /dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
log_header() {
|
log_header() {
|
||||||
rotate_log
|
|
||||||
echo -e "\n${PURPLE}${ICON_ARROW} $1${NC}"
|
echo -e "\n${PURPLE}${ICON_ARROW} $1${NC}"
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] SECTION: $1" >> "$LOG_FILE" 2> /dev/null || true
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] SECTION: $1" >> "$LOG_FILE" 2> /dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Call rotation check once when common.sh is sourced
|
||||||
|
rotate_log_once
|
||||||
|
|
||||||
# Icon output helpers
|
# Icon output helpers
|
||||||
icon_confirm() {
|
icon_confirm() {
|
||||||
echo -e "${BLUE}${ICON_CONFIRM}${NC} $1"
|
echo -e "${BLUE}${ICON_CONFIRM}${NC} $1"
|
||||||
@@ -244,7 +246,7 @@ show_cursor() {
|
|||||||
printf '\033[?25h'
|
printf '\033[?25h'
|
||||||
}
|
}
|
||||||
|
|
||||||
# Keyboard input handling (simple and robust)
|
# Keyboard input handling (simplified)
|
||||||
read_key() {
|
read_key() {
|
||||||
local key rest read_status
|
local key rest read_status
|
||||||
|
|
||||||
@@ -260,7 +262,6 @@ read_key() {
|
|||||||
|
|
||||||
# Raw typing mode (filter): map most keys to CHAR:<key>
|
# Raw typing mode (filter): map most keys to CHAR:<key>
|
||||||
if [[ "${MOLE_READ_KEY_FORCE_CHAR:-}" == "1" ]]; then
|
if [[ "${MOLE_READ_KEY_FORCE_CHAR:-}" == "1" ]]; then
|
||||||
# Some terminals return empty on Enter with -n1
|
|
||||||
if [[ -z "$key" ]]; then
|
if [[ -z "$key" ]]; then
|
||||||
echo "ENTER"
|
echo "ENTER"
|
||||||
return 0
|
return 0
|
||||||
@@ -269,17 +270,13 @@ read_key() {
|
|||||||
$'\n' | $'\r') echo "ENTER" ;;
|
$'\n' | $'\r') echo "ENTER" ;;
|
||||||
$'\x7f' | $'\x08') echo "DELETE" ;;
|
$'\x7f' | $'\x08') echo "DELETE" ;;
|
||||||
$'\x1b') echo "QUIT" ;; # ESC cancels filter
|
$'\x1b') echo "QUIT" ;; # ESC cancels filter
|
||||||
*)
|
[[:print:]]) echo "CHAR:$key" ;;
|
||||||
case "$key" in
|
*) echo "OTHER" ;;
|
||||||
[[:print:]]) echo "CHAR:$key" ;;
|
|
||||||
*) echo "OTHER" ;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Some terminals can yield empty on Enter with -n1; treat as ENTER
|
# Empty key = Enter
|
||||||
if [[ -z "$key" ]]; then
|
if [[ -z "$key" ]]; then
|
||||||
echo "ENTER"
|
echo "ENTER"
|
||||||
return 0
|
return 0
|
||||||
@@ -292,15 +289,14 @@ read_key() {
|
|||||||
'h' | 'H') echo "HELP" ;;
|
'h' | 'H') echo "HELP" ;;
|
||||||
'R') echo "RETRY" ;;
|
'R') echo "RETRY" ;;
|
||||||
'o' | 'O') echo "OPEN" ;;
|
'o' | 'O') echo "OPEN" ;;
|
||||||
'/') echo "FILTER" ;; # Trigger filter mode
|
'/') echo "FILTER" ;;
|
||||||
$'\x03') echo "QUIT" ;; # Ctrl+C
|
$'\x03') echo "QUIT" ;; # Ctrl+C
|
||||||
$'\x7f' | $'\x08') echo "DELETE" ;; # Backspace/Delete key
|
$'\x7f' | $'\x08') echo "DELETE" ;;
|
||||||
$'\x1b')
|
$'\x1b')
|
||||||
# ESC sequence - could be arrow key, delete key, or ESC alone
|
# ESC sequence - could be arrow key, delete key, or ESC alone
|
||||||
# Read the next bytes with 1s timeout for maximum compatibility
|
|
||||||
if IFS= read -r -s -n 1 -t 1 rest 2> /dev/null; then
|
if IFS= read -r -s -n 1 -t 1 rest 2> /dev/null; then
|
||||||
if [[ "$rest" == "[" ]]; then
|
if [[ "$rest" == "[" ]]; then
|
||||||
# Got ESC [, read next character
|
# ESC [ sequence
|
||||||
if IFS= read -r -s -n 1 -t 1 rest2 2> /dev/null; then
|
if IFS= read -r -s -n 1 -t 1 rest2 2> /dev/null; then
|
||||||
case "$rest2" in
|
case "$rest2" in
|
||||||
"A") echo "UP" ;;
|
"A") echo "UP" ;;
|
||||||
@@ -308,74 +304,48 @@ read_key() {
|
|||||||
"C") echo "RIGHT" ;;
|
"C") echo "RIGHT" ;;
|
||||||
"D") echo "LEFT" ;;
|
"D") echo "LEFT" ;;
|
||||||
"3")
|
"3")
|
||||||
# Delete key (Fn+Delete): ESC [ 3 ~
|
# Delete key: ESC [ 3 ~
|
||||||
IFS= read -r -s -n 1 -t 1 rest3 2> /dev/null
|
IFS= read -r -s -n 1 -t 1 rest3 2> /dev/null
|
||||||
if [[ "$rest3" == "~" ]]; then
|
[[ "$rest3" == "~" ]] && echo "DELETE" || echo "OTHER"
|
||||||
echo "DELETE"
|
|
||||||
else
|
|
||||||
echo "OTHER"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
"5")
|
|
||||||
# Page Up key: ESC [ 5 ~
|
|
||||||
IFS= read -r -s -n 1 -t 1 rest3 2> /dev/null
|
|
||||||
[[ "$rest3" == "~" ]] && echo "OTHER" || echo "OTHER"
|
|
||||||
;;
|
|
||||||
"6")
|
|
||||||
# Page Down key: ESC [ 6 ~
|
|
||||||
IFS= read -r -s -n 1 -t 1 rest3 2> /dev/null
|
|
||||||
[[ "$rest3" == "~" ]] && echo "OTHER" || echo "OTHER"
|
|
||||||
;;
|
;;
|
||||||
*) echo "OTHER" ;;
|
*) echo "OTHER" ;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
echo "QUIT" # ESC [ timeout
|
echo "QUIT"
|
||||||
fi
|
fi
|
||||||
elif [[ "$rest" == "O" ]]; then
|
elif [[ "$rest" == "O" ]]; then
|
||||||
# Application keypad mode sequences (mouse wheel often generates these)
|
# ESC O sequence (application keypad mode)
|
||||||
if IFS= read -r -s -n 1 -t 1 rest2 2> /dev/null; then
|
if IFS= read -r -s -n 1 -t 1 rest2 2> /dev/null; then
|
||||||
case "$rest2" in
|
case "$rest2" in
|
||||||
"A") echo "UP" ;; # ESC O A
|
"A") echo "UP" ;;
|
||||||
"B") echo "DOWN" ;; # ESC O B
|
"B") echo "DOWN" ;;
|
||||||
"C") echo "RIGHT" ;; # ESC O C
|
"C") echo "RIGHT" ;;
|
||||||
"D") echo "LEFT" ;; # ESC O D
|
"D") echo "LEFT" ;;
|
||||||
*) echo "OTHER" ;; # Ignore other ESC O sequences
|
*) echo "OTHER" ;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
echo "OTHER" # ESC O timeout
|
echo "OTHER"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "OTHER" # ESC + something else (not [ or O)
|
echo "OTHER"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# ESC pressed alone - treat as quit
|
# ESC alone
|
||||||
echo "QUIT"
|
echo "QUIT"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
[[:print:]]) echo "CHAR:$key" ;;
|
||||||
# Printable ASCII -> expose as CHAR:<key> (for live filtering)
|
*) echo "OTHER" ;;
|
||||||
case "$key" in
|
|
||||||
[[:print:]]) echo "CHAR:$key" ;;
|
|
||||||
*) echo "OTHER" ;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# Drain pending input (useful for scrolling prevention)
|
# Drain pending input (simplified single-pass)
|
||||||
drain_pending_input() {
|
drain_pending_input() {
|
||||||
local drained=0
|
local drained=0
|
||||||
# Multiple passes with very short timeout to catch mouse wheel bursts
|
# Single pass with 0.01s timeout is sufficient for mouse wheel events
|
||||||
# Mouse wheel scrolling can generate rapid sequences like B^[OB^[OB^[O...
|
|
||||||
while IFS= read -r -s -n 1 -t 0.01 _ 2> /dev/null; do
|
while IFS= read -r -s -n 1 -t 0.01 _ 2> /dev/null; do
|
||||||
((drained++))
|
((drained++))
|
||||||
# Safety limit for mouse wheel sequences
|
[[ $drained -gt 100 ]] && break
|
||||||
[[ $drained -gt 200 ]] && break
|
|
||||||
done
|
|
||||||
# Second pass with even shorter timeout to catch any remaining input
|
|
||||||
while IFS= read -r -s -n 1 -t 0.001 _ 2> /dev/null; do
|
|
||||||
((drained++))
|
|
||||||
[[ $drained -gt 500 ]] && break
|
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,7 +839,7 @@ prompt_action() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo -ne "${PURPLE}${ICON_ARROW}${NC} Press ${GREEN}Enter${NC} to ${action}, ${GRAY}ESC${NC} to ${cancel}: "
|
echo -ne "${PURPLE}${ICON_ARROW}${NC} Press ${GREEN}Enter${NC} to ${action}, ${GRAY}ESC${NC} to ${cancel}: "
|
||||||
IFS= read -r -s -n1 key || key=""
|
IFS= read -r -s -n1 key || key=""
|
||||||
drain_pending_input # Clean up any escape sequence remnants
|
drain_pending_input # Clean up any escape sequence remnants
|
||||||
|
|
||||||
case "$key" in
|
case "$key" in
|
||||||
$'\e') # ESC
|
$'\e') # ESC
|
||||||
@@ -893,7 +863,7 @@ confirm_prompt() {
|
|||||||
local message="$1"
|
local message="$1"
|
||||||
echo -n "$message (Enter=OK / ESC q=Cancel): "
|
echo -n "$message (Enter=OK / ESC q=Cancel): "
|
||||||
IFS= read -r -s -n1 _key || _key=""
|
IFS= read -r -s -n1 _key || _key=""
|
||||||
drain_pending_input # Clean up any escape sequence remnants
|
drain_pending_input # Clean up any escape sequence remnants
|
||||||
case "$_key" in
|
case "$_key" in
|
||||||
$'\e' | q | Q)
|
$'\e' | q | Q)
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ decode_file_list() {
|
|||||||
local decoded
|
local decoded
|
||||||
|
|
||||||
# Decode base64 data
|
# Decode base64 data
|
||||||
if ! decoded=$(printf '%s' "$encoded" | base64 -d 2>/dev/null); then
|
if ! decoded=$(printf '%s' "$encoded" | base64 -d 2> /dev/null); then
|
||||||
log_error "Failed to decode file list for $app_name"
|
log_error "Failed to decode file list for $app_name"
|
||||||
echo ""
|
echo ""
|
||||||
return 1
|
return 1
|
||||||
@@ -137,7 +137,7 @@ batch_uninstall_applications() {
|
|||||||
echo -ne "${PURPLE}${ICON_ARROW}${NC} ${removal_note}. Press ${GREEN}Enter${NC} to confirm, ${GRAY}ESC${NC} to cancel: "
|
echo -ne "${PURPLE}${ICON_ARROW}${NC} ${removal_note}. Press ${GREEN}Enter${NC} to confirm, ${GRAY}ESC${NC} to cancel: "
|
||||||
|
|
||||||
IFS= read -r -s -n1 key || key=""
|
IFS= read -r -s -n1 key || key=""
|
||||||
drain_pending_input # Clean up any escape sequence remnants
|
drain_pending_input # Clean up any escape sequence remnants
|
||||||
case "$key" in
|
case "$key" in
|
||||||
$'\e' | q | Q)
|
$'\e' | q | Q)
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
Reference in New Issue
Block a user