diff --git a/src/app/components/DeviceDetailOverlay.tsx b/src/app/components/DeviceDetailOverlay.tsx
index cc7d331..d81615a 100644
--- a/src/app/components/DeviceDetailOverlay.tsx
+++ b/src/app/components/DeviceDetailOverlay.tsx
@@ -94,8 +94,7 @@ export default function DeviceDetailOverlay({
};
const getDevicePath = (): string[] => {
- const [type, num] = device.id.split('-');
- return ['iec', 'devices', type, num];
+ return ['iec', 'devices', device.number];
};
const getDeviceData = () => {
diff --git a/src/app/components/DevicesPage.tsx b/src/app/components/DevicesPage.tsx
index 52bf0ae..e21509c 100644
--- a/src/app/components/DevicesPage.tsx
+++ b/src/app/components/DevicesPage.tsx
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
-import { Printer, HardDrive, Network, Box, ChevronRight, RefreshCw, FolderOpen } from 'lucide-react';
+import { Printer, HardDrive, Network, Box, ChevronRight, RefreshCw, FolderOpen, Computer } from 'lucide-react';
import DeviceDetailOverlay from './DeviceDetailOverlay';
import MediaBrowser from './MediaBrowser';
import { toast } from 'sonner';
@@ -45,77 +45,24 @@ export default function DevicesPage({ config, setConfig, openDeviceId, onClearOp
const devices: Device[] = [];
- // Printer devices
- if (config.iec?.devices?.printer) {
- Object.entries(config.iec.devices.printer).forEach(([num, device]: [string, any]) => {
+ if (config.iec?.devices) {
+ Object.entries(config.iec.devices).forEach(([num, device]: [string, any]) => {
+ const type = device.type as Device['type'];
+ const name = device.name || (
+ type === 'drive' ? `Drive ${num}` :
+ type === 'network' ? `Network ${num}` :
+ type === 'meatloaf' ? `Meatloaf ${num}` :
+ undefined
+ );
devices.push({
- id: `printer-${num}`,
+ id: `${type}-${num}`,
number: num,
- type: 'printer',
- name: device.name,
- enabled: device.enabled
- });
- });
- }
-
- // Drive devices
- if (config.iec?.devices?.drive) {
- Object.entries(config.iec.devices.drive).forEach(([key, value]: [string, any]) => {
- if (key !== 'vdrive' && key !== 'rom') {
- devices.push({
- id: `drive-${key}`,
- number: key,
- type: 'drive',
- name: `Drive ${key}`,
- enabled: value.enabled,
- base_url: value.base_url,
- url: value.url,
- mode: value.mode
- });
- }
- });
- }
-
- // Network devices
- if (config.iec?.devices?.network) {
- Object.entries(config.iec.devices.network).forEach(([num, device]: [string, any]) => {
- devices.push({
- id: `network-${num}`,
- number: num,
- type: 'network',
- name: `Network ${num}`,
- enabled: device.enabled,
- base_url: device.base_url,
- url: device.url
- });
- });
- }
-
- // Other devices
- if (config.iec?.devices?.other) {
- Object.entries(config.iec.devices.other).forEach(([num, device]: [string, any]) => {
- devices.push({
- id: `other-${num}`,
- number: num,
- type: 'other',
- name: device.name,
- enabled: device.enabled
- });
- });
- }
-
- // Meatloaf devices
- if (config.iec?.devices?.meatloaf) {
- Object.entries(config.iec.devices.meatloaf).forEach(([num, device]: [string, any]) => {
- devices.push({
- id: `meatloaf-${num}`,
- number: num,
- type: 'meatloaf',
- name: `Meatloaf ${num}`,
+ type,
+ name,
enabled: device.enabled,
base_url: device.base_url,
url: device.url,
- mode: device.mode
+ mode: device.mode,
});
});
}
@@ -137,6 +84,8 @@ export default function DevicesPage({ config, setConfig, openDeviceId, onClearOp
return ;
case 'network':
return ;
+ case 'meatloaf':
+ return ;
default:
return ;
}
@@ -177,20 +126,9 @@ export default function DevicesPage({ config, setConfig, openDeviceId, onClearOp
const toggleDeviceEnabled = (device: Device, e: React.MouseEvent) => {
e.stopPropagation();
-
- const [type, num] = device.id.split('-');
- const path = ['iec', 'devices', type, num, 'enabled'];
-
const newConfig = JSON.parse(JSON.stringify(config));
- let current = newConfig;
-
- for (let i = 0; i < path.length - 1; i++) {
- current = current[path[i]];
- }
-
- current[path[path.length - 1]] = device.enabled ? 0 : 1;
+ newConfig.iec.devices[device.number].enabled = device.enabled ? 0 : 1;
setConfig(newConfig);
-
toast.success(`Device #${device.number} ${device.enabled ? 'disabled' : 'enabled'}`);
};
diff --git a/src/app/components/MediaManager.tsx b/src/app/components/MediaManager.tsx
index 05933f2..15ae647 100644
--- a/src/app/components/MediaManager.tsx
+++ b/src/app/components/MediaManager.tsx
@@ -738,9 +738,8 @@ export default function MediaManager({ initialPath = '/', rootPath, title, confi
const newConfig = JSON.parse(JSON.stringify(config));
if (!newConfig.iec) newConfig.iec = {};
if (!newConfig.iec.devices) newConfig.iec.devices = {};
- if (!newConfig.iec.devices[deviceType]) newConfig.iec.devices[deviceType] = {};
- if (!newConfig.iec.devices[deviceType][key]) newConfig.iec.devices[deviceType][key] = {};
- const dev = newConfig.iec.devices[deviceType][key];
+ if (!newConfig.iec.devices[key]) newConfig.iec.devices[key] = { type: deviceType };
+ const dev = newConfig.iec.devices[key];
if (mountEntry.name.toLowerCase().endsWith('.lst')) {
try {
@@ -1305,10 +1304,12 @@ export default function MediaManager({ initialPath = '/', rootPath, title, confi
{mountEntry?.name}
{(() => {
- const drives = Object.entries(config?.iec?.devices?.drive ?? {})
- .filter(([k]) => k !== 'vdrive' && k !== 'rom')
+ const allDevices = Object.entries(config?.iec?.devices ?? {});
+ const drives = allDevices
+ .filter(([, v]: [string, any]) => (v as any)?.type === 'drive')
.map(([k, v]: [string, any]) => ({ type: 'drive' as const, key: k, base_url: v?.base_url as string | undefined, url: v?.url as string | undefined, enabled: !!v?.enabled }));
- const meatloafs = Object.entries(config?.iec?.devices?.meatloaf ?? {})
+ const meatloafs = allDevices
+ .filter(([, v]: [string, any]) => (v as any)?.type === 'meatloaf')
.map(([k, v]: [string, any]) => ({ type: 'meatloaf' as const, key: k, base_url: v?.base_url as string | undefined, url: v?.url as string | undefined, enabled: !!v?.enabled }));
const devices = [...drives, ...meatloafs];
if (!devices.length)
diff --git a/src/app/components/SearchOverlay.tsx b/src/app/components/SearchOverlay.tsx
index 7cddd8d..2024832 100644
--- a/src/app/components/SearchOverlay.tsx
+++ b/src/app/components/SearchOverlay.tsx
@@ -121,8 +121,8 @@ export default function SearchOverlay({ config, setConfig, onClose }: SearchOver
const handleMount = (deviceNum: string, result: SearchResult) => {
const newConfig = JSON.parse(JSON.stringify(config));
- if (newConfig.iec?.devices?.drive?.[deviceNum]) {
- newConfig.iec.devices.drive[deviceNum].url = result.path;
+ if (newConfig.iec?.devices?.[deviceNum]) {
+ newConfig.iec.devices[deviceNum].url = result.path;
setConfig(newConfig);
toast.success(`Mounted ${result.name} on Device #${deviceNum}`);
setShowDeviceMenu(null);
@@ -131,10 +131,11 @@ export default function SearchOverlay({ config, setConfig, onClose }: SearchOver
const getAvailableDevices = () => {
const devices: { number: string; name: string; url?: string }[] = [];
- if (config.iec?.devices?.drive) {
- for (const [num, device] of Object.entries(config.iec.devices.drive)) {
- if (num !== 'vdrive' && num !== 'rom' && (device as any).enabled) {
- devices.push({ number: num, name: `Drive ${num}`, url: (device as any).url });
+ if (config.iec?.devices) {
+ for (const [num, device] of Object.entries(config.iec.devices)) {
+ const d = device as any;
+ if (d.type === 'drive' && d.enabled) {
+ devices.push({ number: num, name: `Drive ${num}`, url: d.url });
}
}
}
diff --git a/src/app/components/StatusPage.tsx b/src/app/components/StatusPage.tsx
index dede96f..22c067d 100644
--- a/src/app/components/StatusPage.tsx
+++ b/src/app/components/StatusPage.tsx
@@ -27,10 +27,11 @@ export default function StatusPage({ config, setConfig }: StatusPageProps) {
const [showDeviceOverlay, setShowDeviceOverlay] = useState(false);
// Find the first enabled device as the active device
const findActiveDevice = () => {
- if (config.iec?.devices?.drive) {
- for (const [num, device] of Object.entries(config.iec.devices.drive)) {
- if (num !== 'vdrive' && num !== 'rom' && (device as any).enabled) {
- return { number: num, ...device as any, type: 'drive' };
+ if (config.iec?.devices) {
+ for (const [num, device] of Object.entries(config.iec.devices)) {
+ const d = device as any;
+ if (d.type === 'drive' && d.enabled) {
+ return { number: num, ...d };
}
}
}
@@ -51,8 +52,8 @@ export default function StatusPage({ config, setConfig }: StatusPageProps) {
const switchActiveMedia = (file: string) => {
const newConfig = JSON.parse(JSON.stringify(config));
- if (newConfig.iec?.devices?.drive?.[activeDevice!.number]) {
- newConfig.iec.devices.drive[activeDevice!.number].url = file;
+ if (newConfig.iec?.devices?.[activeDevice!.number]) {
+ newConfig.iec.devices[activeDevice!.number].url = file;
setConfig(newConfig);
}
};
diff --git a/src/imports/config.json b/src/imports/config.json
index 2b9a176..b9892fb 100644
--- a/src/imports/config.json
+++ b/src/imports/config.json
@@ -137,93 +137,99 @@
"bbs": 1
},
"devices": {
- "printer": {
- "4": {
- "enabled": 1,
- "type": "printer",
- "name": "MPS803"
- }
+ "4": {
+ "enabled": 1,
+ "type": "printer",
+ "name": "MPS803"
},
- "drive": {
- "8": {
- "enabled": 1,
- "url": "/sd",
- "mode": 1
- },
- "9": {
- "enabled": 1,
- "url": "/",
- "mode": 1
- },
- "10": {
- "enabled": 1,
- "url": "/",
- "mode": 1
- },
- "11": {
- "enabled": 1,
- "url": "/",
- "mode": 1
- },
- "12": {
- "enabled": 1,
- "url": "/",
- "mode": 1
- },
- "13": {
- "enabled": 1,
- "url": "/",
- "mode": 1
- },
- "14": {
- "enabled": 1,
- "url": "/",
- "mode": 1
- },
- "15": {
- "enabled": 1,
- "url": "/",
- "mode": 1
- }
+ "8": {
+ "enabled": 1,
+ "type": "drive",
+ "url": "/sd",
+ "mode": 1
},
- "network": {
- "16": {
- "enabled": 1,
- "url": "/sd"
- },
- "17": {
- "enabled": 1,
- "url": "/"
- },
- "18": {
- "enabled": 1,
- "url": "/"
- },
- "19": {
- "enabled": 1,
- "url": "/"
- }
+ "9": {
+ "enabled": 1,
+ "type": "drive",
+ "url": "/",
+ "mode": 1
},
- "other": {
- "20": {
- "enabled": 1,
- "name": "CP/m"
- },
- "21": {
- "enabled": 1,
- "name": "S.A.M"
- },
- "29": {
- "enabled": 1,
- "name": "Clock"
- }
+ "10": {
+ "enabled": 1,
+ "type": "drive",
+ "url": "/",
+ "mode": 1
},
- "meatloaf": {
- "30": {
- "enabled": 1,
- "url": "/",
- "mode": 1
- }
+ "11": {
+ "enabled": 1,
+ "type": "drive",
+ "url": "/",
+ "mode": 1
+ },
+ "12": {
+ "enabled": 1,
+ "type": "drive",
+ "url": "/",
+ "mode": 1
+ },
+ "13": {
+ "enabled": 1,
+ "type": "drive",
+ "url": "/",
+ "mode": 1
+ },
+ "14": {
+ "enabled": 1,
+ "type": "drive",
+ "url": "/",
+ "mode": 1
+ },
+ "15": {
+ "enabled": 1,
+ "type": "drive",
+ "url": "/",
+ "mode": 1
+ },
+ "16": {
+ "enabled": 1,
+ "type": "network",
+ "url": "/sd"
+ },
+ "17": {
+ "enabled": 1,
+ "type": "network",
+ "url": "/"
+ },
+ "18": {
+ "enabled": 1,
+ "type": "network",
+ "url": "/"
+ },
+ "19": {
+ "enabled": 1,
+ "type": "network",
+ "url": "/"
+ },
+ "20": {
+ "enabled": 1,
+ "type": "other",
+ "name": "CP/m"
+ },
+ "21": {
+ "enabled": 1,
+ "type": "other",
+ "name": "S.A.M"
+ },
+ "29": {
+ "enabled": 1,
+ "type": "other",
+ "name": "Clock"
+ },
+ "30": {
+ "enabled": 1,
+ "type": "meatloaf",
+ "url": "/",
+ "mode": 1
}
}
},