#!/usr/bin/env bash # ui/peer.module.sh — rendering for peer list data # Both compact (tableless) and table layouts kept for future config switching. _LIST_STYLE="${LIST_STYLE:-compact}" function ui::peer::list_style() { echo "$_LIST_STYLE" } # ====================================================== # Row state helpers # ====================================================== function ui::peer::_is_inactive() { local status="${1:-}" [[ "$status" == "online"* ]] && return 1 return 0 } function ui::peer::status_color() { local is_blocked="${1:-false}" is_restricted="${2:-false}" status="${3:-}" if [[ "$is_blocked" == "true" && "$status" == "online"* ]]; then echo "\033[1;31m" elif [[ "$is_blocked" == "true" ]]; then echo "\033[2;31m" elif [[ "$is_restricted" == "true" && "$status" == "online"* ]]; then echo "\033[1;33m" elif [[ "$is_restricted" == "true" ]]; then echo "\033[2;33m" elif [[ "$status" == "online"* ]]; then echo "\033[1;32m" else echo "\033[2m" fi } # Row color — wraps entire row function ui::peer::_row_color() { local is_blocked="${1:-false}" is_restricted="${2:-false}" status="${3:-}" local inactive=false ui::peer::_is_inactive "$status" && inactive=true if $inactive; then if [[ "$is_blocked" == "true" ]]; then echo "\033[2;31m" # dim red — blocked offline elif [[ "$is_restricted" == "true" ]]; then echo "\033[2;33m" # dim yellow — restricted offline else echo "\033[2m" # dim gray — plain offline fi else if [[ "$is_blocked" == "true" ]]; then echo "\033[1;31m" # bold red — blocked active elif [[ "$is_restricted" == "true" ]]; then echo "\033[1;33m" # bold yellow — restricted active else echo "" # no row color — normal online fi fi } # ====================================================== # Compact layout (tableless) # ====================================================== function ui::peer::list_row_compact() { local w_name="${1:-22}" w_ip="${2:-14}" w_type="${3:-9}" \ w_rule="${4:-6}" w_group="${5:-6}" shift 5 local name="${1:-}" ip="${2:-}" type="${3:-}" rule="${4:-}" \ group="${5:-}" status="${6:-}" last_seen="${7:-}" \ is_blocked="${8:-false}" is_restricted="${9:-false}" local row_color row_color=$(ui::peer::_row_color "$is_blocked" "$is_restricted" "$status") local status_color status_color=$(ui::peer::status_color "$is_blocked" "$is_restricted" "$status") local rule_val="${rule:--}" local group_val="${group:--}" local name_pad ip_pad type_pad ts_pad status_pad name_pad=$(printf "%-${w_name}s" "$name") ip_pad=$(printf "%-${w_ip}s" "$ip") type_pad=$(printf "%-${w_type}s" "$type") ts_pad=$(printf "%-11s" "$last_seen") status_pad=$(printf "%-18s" "$status") local rule_pad_n group_pad_n rule_pad_n=$(( w_rule - ${#rule_val} )) group_pad_n=$(( w_group - ${#group_val} )) [[ $rule_pad_n -lt 0 ]] && rule_pad_n=0 [[ $group_pad_n -lt 0 ]] && group_pad_n=0 if [[ -n "$row_color" ]]; then # Colored row — entire row in row_color, status uses status_color printf " %b%s %s %s \033[2mrule:\033[0m%b %s%*s \033[2mgroup:\033[0m%b %s%*s\033[0m %b%s\033[0m %b%s\033[0m\n" \ "$row_color" \ "$name_pad" "$ip_pad" "$type_pad" \ "$row_color" "$rule_val" "$rule_pad_n" "" \ "$row_color" "$group_val" "$group_pad_n" "" \ "$status_color" "$status_pad" \ "$status_color" "$ts_pad" else # Normal online row — white fields, colored status/last_seen printf " %s %s %s \033[2mrule:\033[0m %s%*s \033[2mgroup:\033[0m %s%*s %b%s\033[0m %b%s\033[0m\n" \ "$name_pad" "$ip_pad" "$type_pad" \ "$rule_val" "$rule_pad_n" "" \ "$group_val" "$group_pad_n" "" \ "$status_color" "$status_pad" \ "$status_color" "$ts_pad" fi } # ====================================================== # Table layout (kept for config switching) # ====================================================== function ui::peer::list_header_table() { local has_groups="${1:-false}" if $has_groups; then printf "\n %-28s %-15s %-13s %-12s %-12s %-22s %s\n" \ "NAME" "IP" "TYPE" "RULE" "GROUP" "STATUS" "LAST SEEN" printf " %s\n" "$(printf '─%.0s' {1..135})" else printf "\n %-28s %-15s %-13s %-12s %-22s %s\n" \ "NAME" "IP" "TYPE" "RULE" "STATUS" "LAST SEEN" printf " %s\n" "$(printf '─%.0s' {1..107})" fi } function ui::peer::list_footer_table() { local has_groups="${1:-false}" if $has_groups; then printf " %s\n" "$(printf '─%.0s' {1..135})" else printf " %s\n" "$(printf '─%.0s' {1..107})" fi } function ui::peer::list_row_table() { local has_groups="${1:-false}" shift local name="${1:-}" ip="${2:-}" type="${3:-}" rule="${4:-}" \ group="${5:-}" status="${6:-}" last_seen="${7:-}" local padded_status padded_status=$(ui::pad_status "$status" 25) if $has_groups; then printf " %-28s %-15s %-13s %-12s %-12s %s %s\n" \ "$name" "$ip" "$type" "${rule:-—}" "${group:-—}" \ "$padded_status" "$last_seen" else printf " %-28s %-15s %-13s %-12s %s %s\n" \ "$name" "$ip" "$type" "${rule:-—}" \ "$padded_status" "$last_seen" fi } # ====================================================== # Detailed layout (grouped by identity) # ====================================================== function ui::peer::list_identity_header() { local identity_name="${1:-}" printf "\n \033[1m%s\033[0m\n" "$identity_name" } function ui::peer::list_row_detailed() { local w_name="${1:-22}" w_ip="${2:-14}" w_type="${3:-9}" \ w_rule="${4:-6}" w_group="${5:-6}" w_subnet="${6:-8}" shift 6 local name="${1:-}" ip="${2:-}" type="${3:-}" rule="${4:-}" \ group="${5:-}" subnet="${6:-}" status="${7:-}" last_seen="${8:-}" \ is_blocked="${9:-false}" is_restricted="${10:-false}" local row_color row_color=$(ui::peer::_row_color "$is_blocked" "$is_restricted" "$status") local status_color status_color=$(ui::peer::status_color "$is_blocked" "$is_restricted" "$status") local rule_val="${rule:--}" local group_val="${group:--}" local subnet_val="${subnet:--}" local name_pad ip_pad type_pad ts_pad status_pad name_pad=$(printf "%-${w_name}s" "$name") ip_pad=$(printf "%-${w_ip}s" "$ip") type_pad=$(printf "%-${w_type}s" "$type") ts_pad=$(printf "%-11s" "$last_seen") status_pad=$(printf "%-18s" "$status") local rule_pad_n group_pad_n subnet_pad_n rule_pad_n=$(( w_rule - ${#rule_val} )) group_pad_n=$(( w_group - ${#group_val} )) subnet_pad_n=$(( w_subnet - ${#subnet_val} )) [[ $rule_pad_n -lt 0 ]] && rule_pad_n=0 [[ $group_pad_n -lt 0 ]] && group_pad_n=0 [[ $subnet_pad_n -lt 0 ]] && subnet_pad_n=0 if [[ -n "$row_color" ]]; then printf " · %b%s %s %s \033[2mrule:\033[0m%b %s%*s \033[2mgroup:\033[0m%b %s%*s \033[2msubnet:\033[0m%b %s%*s\033[0m %b%s\033[0m %b%s\033[0m\n" \ "$row_color" \ "$name_pad" "$ip_pad" "$type_pad" \ "$row_color" "$rule_val" "$rule_pad_n" "" \ "$row_color" "$group_val" "$group_pad_n" "" \ "$row_color" "$subnet_val" "$subnet_pad_n" "" \ "$status_color" "$status_pad" \ "$status_color" "$ts_pad" else printf " · %s %s %s \033[2mrule:\033[0m %s%*s \033[2mgroup:\033[0m %s%*s \033[2msubnet:\033[0m %s%*s %b%s\033[0m %b%s\033[0m\n" \ "$name_pad" "$ip_pad" "$type_pad" \ "$rule_val" "$rule_pad_n" "" \ "$group_val" "$group_pad_n" "" \ "$subnet_val" "$subnet_pad_n" "" \ "$status_color" "$status_pad" \ "$status_color" "$ts_pad" fi }