diff --git a/CHANGELOG.md b/CHANGELOG.md index 2776758..1dcd270 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### 🐛 Bug Fixes - Status Colors on Monitor tab now reflect status of host. Closes #7 +- Removed unused function. ## [0.2.0] - 2026-09-24 ### 🚀 Features diff --git a/src-tauri/src/commands/monitor.rs b/src-tauri/src/commands/monitor.rs index bb5b864..3b3b022 100644 --- a/src-tauri/src/commands/monitor.rs +++ b/src-tauri/src/commands/monitor.rs @@ -180,3 +180,19 @@ pub async fn monitor_stop() -> Result<(), String> { } Ok(()) } +#[tauri::command] +pub async fn monitor_update_label(ip: String, label: String) -> Result<(), String> { + let parsed: IpAddr = ip.parse().map_err(|e| format!("Invalid IP: {}", e))?; + let state = get_monitor(); + let mut guard = state.lock().await; + if let Some(entry) = guard.entries.get_mut(&parsed) { + entry.label = if label.is_empty() { None } else { Some(label) }; + } + Ok(()) +} + +#[tauri::command] +pub async fn monitor_resolve_host(ip: String) -> Result, String> { + let parsed: IpAddr = ip.parse().map_err(|e| format!("Invalid IP: {}", e))?; + Ok(crate::net::dns::reverse_lookup(parsed).await) +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 8a6c46c..43bb668 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -32,6 +32,8 @@ pub fn run() { commands::updater::check_for_update, commands::actions::check_privileges, commands::changelog::get_changelog, + commands::monitor::monitor_update_label, + commands::monitor::monitor_resolve_host ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src/main.js b/src/main.js index 6827aff..d0e7358 100644 --- a/src/main.js +++ b/src/main.js @@ -609,7 +609,7 @@ const sender = (() => { if (action.startsWith('nmap')) { nmapTab.setTarget(hosts.map((h) => String(h.ip))); } else if (action.startsWith('monitor')) { - monitorTab.setTargets(hosts.map(function (h) { return String(h.ip); })); + monitorTab.setTargets(hosts); } document.querySelectorAll('.send-menu').forEach((m) => m.hidden = true); @@ -675,7 +675,8 @@ const ctxMenu = (() => { traceroute.run(ip); break; case 'send-monitor': - monitorTab.setTargets([ip]); + var monHost = table.getAll().find(function (h) { return String(h.ip) === ip; }); + monitorTab.setTargets(monHost ? [monHost] : [ip]); break; case 'send-nmap': nmapTab.setTarget([ip]); @@ -967,7 +968,7 @@ const monitorTab = (() => { return '' + '' + ip + '' - + '' + label + '' + + '' + label + '' + '' + e.status + '' + '' + lastRtt + '' + '' + minRtt + '' @@ -994,6 +995,16 @@ const monitorTab = (() => { try { await invoke('monitor_add_hosts', { hosts: hosts }); + + for (var i = 0; i < hosts.length; i++) { + try { + var hostname = await invoke('monitor_resolve_host', { ip: hosts[i].ip }); + if (hostname) { + await invoke('monitor_update_label', { ip: hosts[i].ip, label: hostname }); + } + } catch (e) { } + } + var updated = await invoke('monitor_get_entries'); entries = {}; updated.forEach(function (e) { entries[e.ip] = e; }); @@ -1048,9 +1059,20 @@ const monitorTab = (() => { } } - function setTargets(ips) { - els.input().value = ips.join(', '); - // Switch to monitor tab + function setTargets(hosts) { + var items = hosts.map(function (h) { + if (typeof h === 'string') return { ip: h, label: null }; + return { ip: String(h.ip), label: h.hostname || null }; + }); + + invoke('monitor_add_hosts', { hosts: items }).then(function () { + return invoke('monitor_get_entries'); + }).then(function (updated) { + entries = {}; + updated.forEach(function (e) { entries[e.ip] = e; }); + render(); + }); + document.querySelectorAll('.tab').forEach(function (t) { t.classList.remove('active'); }); document.querySelectorAll('.view').forEach(function (v) { v.classList.remove('active'); }); document.querySelector('[data-tab="monitor"]').classList.add('active'); @@ -1085,6 +1107,38 @@ const monitorTab = (() => { var btn = e.target.closest('.btn-remove'); if (btn) removeHost(btn.dataset.ip); }); + els.body().addEventListener('dblclick', function (e) { + var cell = e.target.closest('.editable-label'); + if (!cell) return; + var ip = cell.dataset.ip; + var currentLabel = cell.textContent === '-' ? '' : cell.textContent; + + var input = document.createElement('input'); + input.type = 'text'; + input.value = currentLabel; + input.className = 'label-edit-input'; + cell.textContent = ''; + cell.appendChild(input); + input.focus(); + input.select(); + + function save() { + var newLabel = input.value.trim(); + invoke('monitor_update_label', { ip: ip, label: newLabel }).then(function () { + return invoke('monitor_get_entries'); + }).then(function (updated) { + entries = {}; + updated.forEach(function (e) { entries[e.ip] = e; }); + render(); + }); + } + + input.addEventListener('blur', save); + input.addEventListener('keydown', function (ev) { + if (ev.key === 'Enter') save(); + if (ev.key === 'Escape') render(); + }); + }); setupListeners(); } diff --git a/src/styles.css b/src/styles.css index a38e826..58f6ca4 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1494,4 +1494,24 @@ body { :root[data-theme="midnight"] .toolbar-circuit { filter: brightness(0.8); +} + +.editable-label { + cursor: pointer; +} + +.editable-label:hover { + background: var(--cyan-dim); +} + +.label-edit-input { + width: 100%; + padding: 2px 6px; + font-family: var(--font-mono); + font-size: 12px; + color: var(--text-primary); + background: var(--bg-primary); + border: 1px solid var(--cyan); + border-radius: var(--radius); + outline: none; } \ No newline at end of file