| 215 | } |
| 216 | |
| 217 | func (m scanModel) renderIPPanel() string { |
| 218 | title := sectionStyle.Render("IP probes") |
| 219 | if m.ipTotal == 0 { |
| 220 | return title + "\n" + mutedStyle.Render("press i or a to start") |
| 221 | } |
| 222 | pct := 0.0 |
| 223 | if m.ipTotal > 0 { |
| 224 | pct = float64(m.ipDone) / float64(m.ipTotal) |
| 225 | } |
| 226 | bar := m.ipBar.ViewAs(pct) |
| 227 | reach := 0 |
| 228 | for _, r := range m.ips { |
| 229 | if r.Reachable { |
| 230 | reach++ |
| 231 | } |
| 232 | } |
| 233 | summary := fmt.Sprintf("%d/%d reachable=%d", m.ipDone, m.ipTotal, reach) |
| 234 | top := scanner.RankIPs(m.ips) |
| 235 | if len(top) > 10 { |
| 236 | top = top[:10] |
| 237 | } |
| 238 | var lines []string |
| 239 | for i, r := range top { |
| 240 | lines = append(lines, fmt.Sprintf("%2d. %-18s %s", |
| 241 | i+1, r.IP, r.RTT.Round(time.Millisecond))) |
| 242 | } |
| 243 | if len(lines) == 0 { |
| 244 | lines = []string{mutedStyle.Render("no reachable IPs yet")} |
| 245 | } |
| 246 | return strings.Join([]string{title, bar, summary, "", strings.Join(lines, "\n")}, "\n") |
| 247 | } |
| 248 | |
| 249 | // Scan commands -------------------------------------------------------- |
| 250 | |