1
0
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:
Tw93
2025-11-15 13:18:57 +08:00
parent 53ebd90d91
commit 018afa396c
3 changed files with 41 additions and 71 deletions

View File

@@ -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

View File

@@ -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 ""

View File

@@ -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 ""