feat: Telegram fleet alerts, forge sigil scramble, UI polish, agent ops
- Calibrate: per-event Telegram/SMTP toggles, test notification, chat ID help - Notify on agent connect/reconnect, offline/hashrate/rejection, forge complete - Sigil scramble post-forge uniquification and Dispense Reveal ceremony - Full system check, desktop push, BITS/host-binary persistence, Path Tracer - Dashboard/Crucible visual polish, haptics, sacred geometry, mobile nav - README documents alerts, sigil scramble, and pack-usb workflow - USB bundle repacked via pack-usb.bat (AetherForge.exe + synced agent source)
This commit is contained in:
@@ -7,6 +7,11 @@ import {
|
||||
XAxis,
|
||||
YAxis,
|
||||
} from 'recharts';
|
||||
import {
|
||||
chartSeriesDelta,
|
||||
chartSeriesPeak,
|
||||
type ChartDisplayMode,
|
||||
} from '../../help/chartSampleData';
|
||||
import './HashrateChart.css';
|
||||
|
||||
export interface ChartPoint {
|
||||
@@ -21,6 +26,7 @@ interface HashrateChartProps {
|
||||
color?: string;
|
||||
unit?: string;
|
||||
height?: number;
|
||||
displayMode?: ChartDisplayMode;
|
||||
}
|
||||
|
||||
const GRAD_IDS = ['cyan', 'magenta', 'amber', 'green', 'purple'] as const;
|
||||
@@ -39,25 +45,42 @@ export default function HashrateChart({
|
||||
color = '#00f5ff',
|
||||
unit = 'H/s',
|
||||
height = 280,
|
||||
displayMode = 'live',
|
||||
}: HashrateChartProps) {
|
||||
const gradId = colorToId(color);
|
||||
const peak = chartSeriesPeak(data);
|
||||
const delta = chartSeriesDelta(data);
|
||||
const liveLabel =
|
||||
displayMode === 'live' ? '● LIVE' : displayMode === 'blend' ? '● SYNCING' : '● PROJECTION';
|
||||
const liveClass =
|
||||
displayMode === 'live' ? 'pulse' : displayMode === 'blend' ? 'blend' : 'sample';
|
||||
|
||||
if (data.length === 0) {
|
||||
return (
|
||||
<div className="chart-empty neon-chart-panel">
|
||||
<div className="chart-empty neon-chart-panel wealth-empty">
|
||||
<div className="chart-empty-icon">◈</div>
|
||||
<p className="font-tech">{title || 'Telemetry'}</p>
|
||||
<span>Awaiting signal from fleet...</span>
|
||||
<span>Calibrating chart telemetry…</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="chart-wrap neon-chart-panel">
|
||||
<div className="chart-wrap neon-chart-panel wealth-chart">
|
||||
{title && (
|
||||
<div className="chart-header">
|
||||
<h3 className="chart-title font-display">{title}</h3>
|
||||
<span className="chart-live pulse">● LIVE</span>
|
||||
<div className="chart-header-meta">
|
||||
<span className="chart-peak font-tech">
|
||||
PEAK {formatFull(peak, unit)}
|
||||
</span>
|
||||
{delta != null && (
|
||||
<span className={`chart-delta font-tech ${delta >= 0 ? 'up' : 'down'}`}>
|
||||
{delta >= 0 ? '▲' : '▼'} {Math.abs(delta).toFixed(1)}%
|
||||
</span>
|
||||
)}
|
||||
<span className={`chart-live ${liveClass}`}>{liveLabel}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<ResponsiveContainer width="100%" height={height}>
|
||||
|
||||
Reference in New Issue
Block a user