6 Commits
8 changed files with 258 additions and 8 deletions
+8 -1
View File
@@ -1,9 +1,16 @@
## [unreleased] ## [0.3.0] - 2026-10-08
### 🚀 Features
- Added Auto Labeling to Montior Tab. When sending hosts from the scan tab, it will bring their hostnames over to the label section. When adding a one off host to the montior tab, it will auto query it's hostname. You can also edit labels by double clicking. Closes #3
- Added Always on Top Toggle. Closes #5
- Added New Theme
### 🐛 Bug Fixes ### 🐛 Bug Fixes
- Status Colors on Monitor tab now reflect status of host. Closes #7 - Status Colors on Monitor tab now reflect status of host. Closes #7
- Removed unused function. - Removed unused function.
- Fixed Screen Refresh Bug on Monitor Tab. Now When You Go To Change a Label While the Monitor Is Running. The Page Stops Refreshing Until You’re Done Changing the Name. This Is To Prevent Your Text Box From Being Deselected When the Table Refreshes.
## [0.2.0] - 2026-09-24 ## [0.2.0] - 2026-09-24
### 🚀 Features ### 🚀 Features
+1 -1
View File
@@ -49,7 +49,7 @@ checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
[[package]] [[package]]
name = "argus" name = "argus"
version = "0.2.0" version = "0.3.0"
dependencies = [ dependencies = [
"csv", "csv",
"dns-lookup", "dns-lookup",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "argus" name = "argus"
version = "0.2.0" version = "0.3.0"
description = "An All in One Network Utility" description = "An All in One Network Utility"
authors = ["James Brotosky <james.brotosky@racooncity.org"] authors = ["James Brotosky <james.brotosky@racooncity.org"]
edition = "2021" edition = "2021"
+2 -1
View File
@@ -6,6 +6,7 @@
"permissions": [ "permissions": [
"core:default", "core:default",
"opener:default", "opener:default",
"dialog:default" "dialog:default",
"core:window:allow-set-always-on-top"
] ]
} }
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"$schema": "https://schema.tauri.app/config/2", "$schema": "https://schema.tauri.app/config/2",
"productName": "argus", "productName": "argus",
"version": "0.2.0", "version": "0.3.0",
"identifier": "io.argus.app", "identifier": "io.argus.app",
"build": { "build": {
"frontendDist": "../src" "frontendDist": "../src"
+6 -1
View File
@@ -200,12 +200,17 @@
<div id="status-bar"> <div id="status-bar">
<span class="status-bar-item" id="status-bar-version">Argus</span> <span class="status-bar-item" id="status-bar-version">Argus</span>
<button id="btn-changelog" class="status-bar-btn">Changelog</button> <button id="btn-changelog" class="status-bar-btn">Changelog</button>
<label class="toggle-label status-bar-toggle">
<input type="checkbox" id="chk-always-on-top" />
<span>Always on Top</span>
</label>
<select id="theme-picker" class="theme-picker"> <select id="theme-picker" class="theme-picker">
<option value="cyber">Cyber</option> <option value="cyber">Cyber</option>
<option value="midnight">Midnight</option> <option value="midnight">Midnight</option>
<option value="dracula">Dracula</option> <option value="dracula">Dracula</option>
<option value="nord">Nord</option> <option value="nord">Nord</option>
<option value="solarized">Solarized Dark</option> <option value="solarized">Solarized Dark</option>
<option value="mocha">Catppuccin Mocha</option>
</select> </select>
<span class="status-bar-item" id="privilege-status">unprivileged</span> <span class="status-bar-item" id="privilege-status">unprivileged</span>
</div> </div>
@@ -243,7 +248,7 @@
<button class="ctx-item" data-action="send-monitor">Send to Monitor</button> <button class="ctx-item" data-action="send-monitor">Send to Monitor</button>
<button class="ctx-item" data-action="send-nmap">Send to Nmap</button> <button class="ctx-item" data-action="send-nmap">Send to Nmap</button>
</div> </div>
<div id="crt-overlay"></div>
<script src="main.js"></script> <script src="main.js"></script>
</body> </body>
+62 -2
View File
@@ -22,15 +22,63 @@ var theme = (() => {
} catch (e) { } } catch (e) { }
} }
var HACKER_KEY = 'argus-hacker-unlocked';
function isHackerUnlocked() {
try {
return localStorage.getItem(HACKER_KEY) === 'true';
} catch (e) {
return false;
}
}
function unlockHacker() {
try {
localStorage.setItem(HACKER_KEY, 'true');
} catch (e) { }
addHackerOption();
}
function addHackerOption() {
var picker = document.getElementById('theme-picker');
if (!picker.querySelector('option[value="hacker"]')) {
var opt = document.createElement('option');
opt.value = 'hacker';
opt.textContent = '\u2588 H4CK3R';
picker.appendChild(opt);
}
}
function init() { function init() {
var saved = get(); var saved = get();
set(saved); set(saved);
// Add hacker option if previously unlocked
if (isHackerUnlocked()) {
addHackerOption();
}
var picker = document.getElementById('theme-picker'); var picker = document.getElementById('theme-picker');
picker.value = saved; picker.value = saved;
picker.addEventListener('change', function () { picker.addEventListener('change', function () {
set(picker.value); set(picker.value);
}); });
// Easter egg: listen on the scan input
var scanInput = document.getElementById('ip-range-input');
scanInput.addEventListener('input', function () {
var val = scanInput.value.toLowerCase().trim();
if (val === 'all your base are belong to us') {
if (!isHackerUnlocked()) {
unlockHacker();
set('hacker');
picker.value = 'hacker';
scanInput.value = '';
console.log('%c> ACCESS GRANTED', 'color: #00ff41; font-size: 20px; font-family: monospace;');
console.log('%c> HACKER THEME UNLOCKED', 'color: #00ff41; font-size: 14px; font-family: monospace;');
}
}
});
} }
// Apply immediately (before DOMContentLoaded) to prevent flash // Apply immediately (before DOMContentLoaded) to prevent flash
@@ -927,6 +975,7 @@ const nmapTab = (() => {
const monitorTab = (() => { const monitorTab = (() => {
let running = false; let running = false;
let entries = {}; let entries = {};
var editingLabel = false;
var els = { var els = {
input: () => document.getElementById('monitor-input'), input: () => document.getElementById('monitor-input'),
@@ -953,6 +1002,7 @@ const monitorTab = (() => {
} }
function render() { function render() {
if (editingLabel) return;
var body = els.body(); var body = els.body();
var ips = Object.keys(entries).sort(); var ips = Object.keys(entries).sort();
@@ -1112,7 +1162,7 @@ const monitorTab = (() => {
if (!cell) return; if (!cell) return;
var ip = cell.dataset.ip; var ip = cell.dataset.ip;
var currentLabel = cell.textContent === '-' ? '' : cell.textContent; var currentLabel = cell.textContent === '-' ? '' : cell.textContent;
editingLabel = true;
var input = document.createElement('input'); var input = document.createElement('input');
input.type = 'text'; input.type = 'text';
input.value = currentLabel; input.value = currentLabel;
@@ -1124,6 +1174,7 @@ const monitorTab = (() => {
function save() { function save() {
var newLabel = input.value.trim(); var newLabel = input.value.trim();
editingLabel = false;
invoke('monitor_update_label', { ip: ip, label: newLabel }).then(function () { invoke('monitor_update_label', { ip: ip, label: newLabel }).then(function () {
return invoke('monitor_get_entries'); return invoke('monitor_get_entries');
}).then(function (updated) { }).then(function (updated) {
@@ -1136,7 +1187,9 @@ const monitorTab = (() => {
input.addEventListener('blur', save); input.addEventListener('blur', save);
input.addEventListener('keydown', function (ev) { input.addEventListener('keydown', function (ev) {
if (ev.key === 'Enter') save(); if (ev.key === 'Enter') save();
if (ev.key === 'Escape') render(); if (ev.key === 'Escape')
editingLabel = false;
render();
}); });
}); });
@@ -1250,6 +1303,13 @@ window.addEventListener('DOMContentLoaded', () => {
updater.init(); updater.init();
changelog.init(); changelog.init();
theme.init(); theme.init();
// Always on top toggle
document.getElementById('chk-always-on-top').addEventListener('change', function (e) {
if (window.__TAURI__ && window.__TAURI__.window) {
var current = window.__TAURI__.window.getCurrentWindow();
current.setAlwaysOnTop(e.target.checked);
}
});
document.getElementById('btn-export-all').addEventListener('click', exporter.csvAll); document.getElementById('btn-export-all').addEventListener('click', exporter.csvAll);
document.getElementById('btn-export-up').addEventListener('click', exporter.csvUp); document.getElementById('btn-export-up').addEventListener('click', exporter.csvUp);
console.log('[Argus] Ready'); console.log('[Argus] Ready');
+177
View File
@@ -1478,6 +1478,174 @@ body {
--danger-hover: #c62825; --danger-hover: #c62825;
} }
/* ===== Theme: Catppuccin Mocha ===== */
:root[data-theme="mocha"] {
--bg-primary: #1e1e2e;
--bg-secondary: #181825;
--bg-tertiary: #313244;
--bg-hover: #45475a;
--bg-active: #585b70;
--border: #313244;
--border-bright: #45475a;
--text-primary: #cdd6f4;
--text-secondary: #a6adc8;
--text-muted: #6c7086;
--cyan: #89b4fa;
--cyan-hover: #7ba4eb;
--cyan-dim: rgba(137, 180, 250, 0.08);
--cyan-glow: rgba(137, 180, 250, 0.2);
--cyan-subtle: rgba(137, 180, 250, 0.03);
--status-up: #a6e3a1;
--status-up-glow: rgba(166, 227, 161, 0.15);
--status-down: #f38ba8;
--status-down-glow: rgba(243, 139, 168, 0.15);
--status-filtered: #f9e2af;
--status-filtered-glow: rgba(249, 226, 175, 0.15);
--status-unknown: #6c7086;
--danger: #f38ba8;
--danger-hover: #e57a97;
}
:root[data-theme="mocha"] .toolbar-circuit {
filter: hue-rotate(40deg) saturate(0.6) brightness(0.9);
}
:root[data-theme="latte"] .port-tag {
background: rgba(30, 102, 245, 0.1);
border-color: rgba(30, 102, 245, 0.2);
}
:root[data-theme="latte"] #privilege-status::before {
background: var(--status-up);
box-shadow: 0 0 4px rgba(64, 160, 43, 0.3);
}
:root[data-theme="latte"] ::-webkit-scrollbar-track {
background: var(--bg-primary);
}
:root[data-theme="latte"] ::-webkit-scrollbar-thumb {
background: var(--border-bright);
}
/* ===== Theme: Hacker (Easter Egg) ===== */
:root[data-theme="hacker"] {
--bg-primary: #000000;
--bg-secondary: #0a0a0a;
--bg-tertiary: #0d0d0d;
--bg-hover: #1a1a1a;
--bg-active: #222222;
--border: #0a3a0a;
--border-bright: #0f4f0f;
--text-primary: #00ff41;
--text-secondary: #00cc33;
--text-muted: #006b1d;
--cyan: #00ff41;
--cyan-hover: #00dd38;
--cyan-dim: rgba(0, 255, 65, 0.06);
--cyan-glow: rgba(0, 255, 65, 0.3);
--cyan-subtle: rgba(0, 255, 65, 0.02);
--status-up: #00ff41;
--status-up-glow: rgba(0, 255, 65, 0.2);
--status-down: #ff0040;
--status-down-glow: rgba(255, 0, 64, 0.2);
--status-filtered: #ffff00;
--status-filtered-glow: rgba(255, 255, 0, 0.15);
--status-unknown: #006b1d;
--danger: #ff0040;
--danger-hover: #dd0038;
--font-mono: "Courier New", "Lucida Console", monospace;
--font-sans: "Courier New", "Lucida Console", monospace;
}
:root[data-theme="hacker"] .toolbar-circuit {
filter: hue-rotate(-60deg) saturate(3) brightness(0.8);
}
:root[data-theme="hacker"] body {
font-family: "Courier New", "Lucida Console", monospace;
}
:root[data-theme="hacker"] .app-title {
letter-spacing: 5px;
}
:root[data-theme="hacker"] .btn-primary {
text-shadow: 0 0 8px rgba(0, 255, 65, 0.5);
}
:root[data-theme="hacker"] #results-table td,
:root[data-theme="hacker"] #monitor-table td {
text-shadow: 0 0 3px rgba(0, 255, 65, 0.15);
}
#crt-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
z-index: 9999;
}
:root[data-theme="hacker"] #crt-overlay {
display: block;
background:
repeating-linear-gradient(0deg,
rgba(0, 0, 0, 0.4) 0px,
rgba(0, 0, 0, 0.4) 1px,
transparent 1px,
transparent 4px),
linear-gradient(180deg,
transparent 0%,
rgba(0, 255, 65, 0.03) 50%,
transparent 100%);
animation: crt-flicker 3s infinite;
}
@keyframes crt-flicker {
0% {
opacity: 1;
}
5% {
opacity: 0.85;
}
10% {
opacity: 1;
}
40% {
opacity: 0.95;
}
45% {
opacity: 1;
}
80% {
opacity: 0.9;
}
85% {
opacity: 1;
}
}
/* ===== Circuit art theme tinting ===== */ /* ===== Circuit art theme tinting ===== */
:root[data-theme="dracula"] .toolbar-circuit { :root[data-theme="dracula"] .toolbar-circuit {
@@ -1514,4 +1682,13 @@ body {
border: 1px solid var(--cyan); border: 1px solid var(--cyan);
border-radius: var(--radius); border-radius: var(--radius);
outline: none; outline: none;
}
.status-bar-toggle {
font-size: 11px;
color: var(--text-muted);
}
.status-bar-toggle input:checked+span {
color: var(--cyan);
} }