This commit is contained in:
Lucas
2026-09-29 16:59:54 +02:00
parent d5a2afdea5
commit 6511d9d007
7 changed files with 57 additions and 36 deletions
-2
View File
@@ -46,7 +46,6 @@ pub struct DSP408Snapshot {
pub state: types::DSPState,
pub input_meters: types::InputMeters,
pub output_meters: types::OutputMeters,
pub mode: types::DSPMode,
}
#[tauri::command]
@@ -104,7 +103,6 @@ pub async fn get_dsp_snapshot(
state: device.dsp.state().clone(),
input_meters: device.dsp.input_meters().clone(),
output_meters: device.dsp.output_meters().clone(),
mode: device.dsp.mode(),
})
})
}
+2 -2
View File
@@ -1,6 +1,6 @@
import { useState, useEffect, useRef } from 'react';
import './App.css';
import { DSP, AppPage } from './types';
import { DSP, AppPage, isConnected } from './types';
import TopBar from './components/Topbar/Topbar';
import DSPPage from './pages/DspPage/DspPage';
import AddDSPForm from './pages/AddDspPage/AddDspPage';
@@ -17,7 +17,7 @@ function App() {
const [selected, setSelected] = useState<number | null>(null);
const [page, setPage] = useState<AppPage>('home');
const { notifications, notify, removeNotification, hoverNotification } = useNotifications();
const connectedDspCount = dsps.filter((dsp) => dsp.status === 'connected').length;
const connectedDspCount = dsps.filter((dsp) => isConnected(dsp)).length;
const activeDsp = dsps.find((d) => d.id === selected) ?? null;
const activeInstance = activeDsp ? createDSPInstance(activeDsp, setDsps, notify) : null;
+13 -5
View File
@@ -1,5 +1,5 @@
import { useEffect, useRef } from 'react';
import { DSP, AppPage } from '../../types';
import { DSP, AppPage, isConnected } from '../../types';
import AnimatedLogo from '../../assets/icons/AnimatedLogo';
import { PlusIcon } from '../../assets/icons/PlusIcon';
import { CrownIcon } from '../../assets/icons/CrownIcon';
@@ -36,7 +36,7 @@ function Tab({
onDisconnect: (dsp: DSP) => void;
actions?: React.ReactNode;
}) {
const isConnected = dsp.status === 'connected';
const isDspConnected = isConnected(dsp);
const handleTabKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
if (e.key === 'Enter' || e.key === ' ') {
@@ -60,18 +60,26 @@ function Tab({
<button
type="button"
className="tab-led"
aria-label={isConnected ? `Disconnect ${dsp.name}` : `Connect ${dsp.name}`}
aria-label={isDspConnected ? `Disconnect ${dsp.name}` : `Connect ${dsp.name}`}
onClick={(e) => {
e.stopPropagation();
if (isConnected) {
if (isDspConnected) {
onDisconnect(dsp);
} else {
onConnect(dsp);
}
}}
>
<Led status={dsp.status} />
<Led
status={
dsp.isConnecting
? 'connecting'
: isConnected(dsp)
? 'connected'
: 'disconnected'
}
/>
</button>
<span className="tab-name" title={dsp.name}>
@@ -1,4 +1,4 @@
import { DSP } from '../../../../types';
import { DSP, isConnected } from '../../../../types';
import Button from '../../../../components/Button/Button';
import Card from '../../../../components/Card/Card';
import Led from '../../../../components/Led/Led';
@@ -15,12 +15,19 @@ function ConnectionPanel({
onDisconnect: () => void;
}) {
const statusLabel =
dsp.status === 'connected'
isConnected(dsp)
? 'Connected'
: dsp.status === 'connecting'
: dsp.isConnecting
? 'Connecting…'
: 'Disconnected';
console.log('ConnectionPanel render:', {
id: dsp.id,
connection: dsp.type === 'DSP408' ? dsp.state.connection : undefined,
isConnected: isConnected(dsp),
isConnecting: dsp.isConnecting,
});
return (
<div className="connection-section">
<Card className="connection-panel">
@@ -35,10 +42,10 @@ function ConnectionPanel({
<div className="connection-panel__status">
<span className="connection-panel__led">
<Led status={dsp.status} />
{/* <Led status={dsp.status} /> */}
</span>
<span className={`status-label status-label--${dsp.status}`}>{statusLabel}</span>
{/* <span className={`status-label status-label--${dsp.status}`}>{statusLabel}</span> */}
</div>
</div>
@@ -64,13 +71,13 @@ function ConnectionPanel({
</dl>
<div className="connection-panel__actions">
{dsp.status === 'connected' ? (
{isConnected(dsp) ? (
<Button variant="outline" onClick={onDisconnect}>
Disconnect
</Button>
) : (
<Button variant="primary" onClick={onConnect} disabled={dsp.status === 'connecting'}>
{dsp.status === 'connecting' ? 'Connecting…' : 'Connect'}
<Button variant="primary" onClick={onConnect} disabled={dsp.isConnecting}>
{dsp.isConnecting ? 'Connecting…' : 'Connect'}
</Button>
)}
</div>
+10 -12
View File
@@ -12,6 +12,7 @@ import {
PEQBand,
InputSource,
DSP408Snapshot,
DSPMode,
} from './types';
import { SetDsps, NotifyFn, updateDSP, setPollingPaused } from '../../dsp/dspShared';
import { registerPollStopper } from '../../dsp/pollRegistry';
@@ -117,8 +118,8 @@ export async function create(params: {
ip: params.ip,
port: params.port,
deviceId: params.deviceId,
mode: snapshot.mode,
status: 'disconnected',
mode: params.demo ? DSPMode.Demo: DSPMode.Normal,
isConnecting: false,
pollingPaused: true,
state: snapshot.state,
input_meters: snapshot.input_meters,
@@ -130,6 +131,7 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
async function updateDSPState(): Promise<DSP408['state']> {
try {
const state = await invoke<DSP408['state']>('get_dsp_state', { id: dsp.id });
updateDSP(setDsps, dsp.id, (d) => ({ ...d, state }) as DSP408);
return state;
@@ -143,11 +145,11 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
async function abortLocked() {
await invoke('disconnect_dsp408', { id: dsp.id }).catch(() => {});
updateDSP(setDsps, dsp.id, (d) => ({ ...d, status: 'disconnected', passwordRequired: true }));
updateDSP(setDsps, dsp.id, (d) => ({ ...d, passwordRequired: true }));
}
async function connectInternal(password?: string) {
updateDSP(setDsps, dsp.id, (d) => ({ ...d, status: 'connecting', passwordRequired: false }));
updateDSP(setDsps, dsp.id, (d) => ({ ...d, isConnecting: true, passwordRequired: false }));
try {
await invoke('connect_dsp408', { id: dsp.id });
@@ -159,13 +161,10 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
return;
}
try {
await invoke('unlock_device', { id: dsp.id, password }); // adjust name/signature
} catch {
// wrong password
}
let r = await invoke('unlock_device', { id: dsp.id, password });
state = await updateDSPState();
if (isLocked(state)) {
await abortLocked();
notify('Wrong password', 'error', dsp.name);
@@ -173,11 +172,11 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
}
}
updateDSP(setDsps, dsp.id, (d) => ({ ...d, status: 'connected', pollingPaused: false }));
updateDSP(setDsps, dsp.id, (d) => ({ ...d, isConnecting: false, pollingPaused: false }));
notify('Connected', 'success', dsp.name);
startPolling(dsp, setDsps);
} catch (err) {
updateDSP(setDsps, dsp.id, (d) => ({ ...d, status: 'disconnected' }));
updateDSP(setDsps, dsp.id, (d) => ({ ...d, isConnecting: false }));
notify(`Connection failed: ${String(err)}`, 'error', dsp.name);
}
}
@@ -216,7 +215,6 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
updateDSP(setDsps, dsp.id, (d) => ({
...d,
status: 'disconnected',
pollingPaused: true,
}));
+10 -2
View File
@@ -243,15 +243,23 @@ export type DSPState = {
flags: DeviceFlags;
presets: PresetBank;
current_config: DSPConfigState;
connection: ConnectionStatus,
};
export type DSPMode = 'demo' | 'disconnected' | 'connected';
export enum ConnectionStatus {
Connected,
Disconnected,
}
export enum DSPMode {
Demo,
Normal,
}
export type DSP408Snapshot = {
state: DSPState;
input_meters: DSP408InputMeters;
output_meters: DSP408OutputMeters;
mode: DSPMode;
};
export interface Meter {
+7 -5
View File
@@ -3,10 +3,9 @@ import {
DSPMode,
DSP408OutputMeters,
DSP408InputMeters,
ConnectionStatus,
} from './features/dsp408/types';
export type DSPStatus = 'connected' | 'connecting' | 'disconnected';
export type NotificationType = 'success' | 'error' | 'warning';
export type Notification = {
id: number;
@@ -39,12 +38,15 @@ interface DSPBase {
mode: DSPMode;
passwordRequired?: boolean;
status: DSPStatus;
isConnecting: boolean;
pollingPaused: boolean;
}
export function isConnected(dsp: DSP): boolean {
return dsp.type === 'DSP408'
&& dsp.state.connection === ConnectionStatus.Connected;
}
export type DSP408 = DSPBase & {
type: 'DSP408';
state: DSP408State;