;
}) {
const statusBg = (status: string) =>
({
@@ -449,8 +459,11 @@ function MinerTable({
? Math.max(...info.boards.map((b) => b.inTmp))
: null;
const activePool = info.pools.find((p) => p.connect);
+ const isMuted = !!muted[info.ip];
const rowBg = isSelected
? "bg-primary-500/10 hover:bg-primary-500/15"
+ : isMuted
+ ? "bg-amber-500/5 hover:bg-amber-500/10 border-l-2 border-l-amber-500/50"
: i % 2 === 0
? "bg-dark-800 hover:bg-dark-700/50"
: "bg-dark-800/60 hover:bg-dark-700/50";
@@ -499,10 +512,14 @@ function MinerTable({
| {info.ip} |
-
- {info.status}
+
+ {isMuted ? "Muted" : info.status}
|
@@ -611,8 +628,19 @@ export default function MinerList() {
const [allUptimeStats, setAllUptimeStats] = useState>({});
+ const [muted, setMuted] = useState>({});
+
const [showAddPanel, setShowAddPanel] = useState(false);
+ const loadMuted = useCallback(async () => {
+ try {
+ const map = await invoke>("get_muted_devices");
+ setMuted(map);
+ } catch (err) {
+ console.error("Failed to load muted devices:", err);
+ }
+ }, []);
+
// Sync coin filter if URL param changes
useEffect(() => {
const coinParam = searchParams.get("coin");
@@ -625,6 +653,10 @@ export default function MinerList() {
.catch(console.error);
}, []);
+ useEffect(() => {
+ loadMuted();
+ }, [loadMuted]);
+
const loadFromCache = useCallback(async (saved: SavedMiner[]) => {
try {
const [cached, pollTime] = await Promise.all([
@@ -692,6 +724,7 @@ export default function MinerList() {
let cancelled = false;
listen("farm-state-updated", () => {
loadFromCache(savedMiners).catch(console.error);
+ loadMuted();
}).then((h) => {
if (cancelled) h();
else unlisten = h;
@@ -700,7 +733,7 @@ export default function MinerList() {
cancelled = true;
if (unlisten) unlisten();
};
- }, [savedMiners, loadFromCache]);
+ }, [savedMiners, loadFromCache, loadMuted]);
async function handleManualRefresh() {
setRefreshing(true);
@@ -1325,6 +1358,7 @@ export default function MinerList() {
uptimeStats={allUptimeStats}
coinIconByIp={coinIconByIp}
onRemove={(ip) => openRemoveModal([ip])}
+ muted={muted}
/>
) : (
@@ -1340,6 +1374,7 @@ export default function MinerList() {
uptimeStats={allUptimeStats[d.info.ip]}
coinIcon={coinIconByIp[d.info.ip]}
onRemove={() => openRemoveModal([d.info.ip])}
+ isMuted={!!muted[d.info.ip]}
/>
))}
diff --git a/src/pages/MobileMinerList.tsx b/src/pages/MobileMinerList.tsx
index d399dee..2294350 100644
--- a/src/pages/MobileMinerList.tsx
+++ b/src/pages/MobileMinerList.tsx
@@ -150,6 +150,7 @@ function MobileMinerCard({
onRemove,
history,
coinIcon,
+ isMuted = false,
}: {
miner: MobileMiner;
onClick: () => void;
@@ -159,6 +160,7 @@ function MobileMinerCard({
onRemove: () => void;
history: HistoryPoint[];
coinIcon: string | null;
+ isMuted?: boolean;
}) {
const onlineState = deriveOnlineState(miner);
const statusColor = {
@@ -182,6 +184,8 @@ function MobileMinerCard({
className={`bg-dark-800 rounded-xl border p-5 cursor-pointer transition-all relative ${
selectionMode && selected
? "border-primary-500 bg-primary-500/5"
+ : isMuted
+ ? "border-amber-500/40 bg-amber-500/5 hover:border-amber-500/60"
: "border-slate-700/50 hover:border-primary-500/50 hover:bg-dark-800/80"
}`}
onClick={handleCardClick}
@@ -235,10 +239,14 @@ function MobileMinerCard({
{!selectionMode && (
-
- {statusLabel}
+
+ {isMuted ? "Muted" : statusLabel}
|