complete Device List component.
This commit is contained in:
parent
044a17f569
commit
1630c0ea64
@ -56,24 +56,37 @@ export const DeviceState = atomWithRefresh<PeripheralItem | null>(async (get) =>
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
export const FoundPeripherals = atom(
|
const Peripherals = atom<PeripheralItem[]>([]);
|
||||||
[] as PeripheralItem[],
|
export const FoundPeripherals = atom(null, (get, set, item: PeripheralItem | typeof RESET) => {
|
||||||
(get, set, item: PeripheralItem | typeof RESET) => {
|
if (item === RESET) {
|
||||||
if (item === RESET) {
|
void set(Peripherals, []);
|
||||||
void set(FoundPeripherals, []);
|
} else {
|
||||||
} else {
|
void set(Peripherals, (prev) => {
|
||||||
void set(FoundPeripherals, (prev) => {
|
let replaced = false;
|
||||||
const foundIndex = prev.findIndex((i) => i.id === item.id);
|
const newPeripherals = prev.map((i) => {
|
||||||
if (foundIndex !== -1) {
|
if (i.id === item.id) {
|
||||||
prev[foundIndex] = item;
|
replaced = true;
|
||||||
|
return item;
|
||||||
} else {
|
} else {
|
||||||
prev.push(item);
|
return i;
|
||||||
}
|
}
|
||||||
return prev;
|
|
||||||
});
|
});
|
||||||
}
|
if (!replaced) {
|
||||||
},
|
newPeripherals.push(item);
|
||||||
);
|
}
|
||||||
|
return newPeripherals;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
export const AvailablePeripherals = atom((get) => {
|
||||||
|
const peripherals = get(Peripherals);
|
||||||
|
return peripherals.filter((i) => !i.isUnknown);
|
||||||
|
});
|
||||||
|
export const UnknownPeripherals = atom((get) => {
|
||||||
|
const peripherals = get(Peripherals);
|
||||||
|
console.debug('[origin peripherals]', peripherals);
|
||||||
|
return peripherals.filter((i) => i.isUnknown);
|
||||||
|
});
|
||||||
const Channels: Record<Channels, PrimitiveAtom<ChannelState>> = {
|
const Channels: Record<Channels, PrimitiveAtom<ChannelState>> = {
|
||||||
a: atomWithRefresh<ChannelState>(async (get) => {
|
a: atomWithRefresh<ChannelState>(async (get) => {
|
||||||
try {
|
try {
|
||||||
|
@ -5,4 +5,43 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
.devices_list_layout {
|
||||||
|
padding-inline: calc(var(--spacing) * 2);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: calc(var(--spacing) * 4);
|
||||||
|
}
|
||||||
|
.devices_list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: calc(var(--spacing) * 2);
|
||||||
|
.device_card {
|
||||||
|
padding-inline: calc(var(--spacing) * 2);
|
||||||
|
padding-block: calc(var(--spacing) * 3);
|
||||||
|
border-radius: calc(var(--border-radius) * 2);
|
||||||
|
background-color: var(--color-dark-surface);
|
||||||
|
color: var(--color-dark-on-surface);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: calc(var(--spacing) * 1);
|
||||||
|
.device_name {
|
||||||
|
flex: 1;
|
||||||
|
font-size: calc(var(--font-size) * 1.3);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background-color: color-mix(in oklch, var(--color-dark-on-surface) 8%, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.empty_prompt {
|
||||||
|
padding-block: calc(var(--spacing) * 1);
|
||||||
|
text-align: center;
|
||||||
|
font-size: calc(var(--font-size) * 0.8);
|
||||||
|
color: var(--color-dark-on-surface-variant);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,34 @@
|
|||||||
|
import { useAtomValue } from 'jotai';
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { ScrollArea } from '../../components/ScrollArea';
|
import { ScrollArea } from '../../components/ScrollArea';
|
||||||
|
import { AvailablePeripherals } from '../../context/EstimContext';
|
||||||
|
import IconRssi from '../../icons/IconRssi';
|
||||||
import styles from './DeviceList.module.css';
|
import styles from './DeviceList.module.css';
|
||||||
|
|
||||||
|
const AvailableDevices: FC = () => {
|
||||||
|
const devices = useAtomValue(AvailablePeripherals);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.devices_list}>
|
||||||
|
{devices.length === 0 && <div className={styles.empty_prompt}>No available devices.</div>}
|
||||||
|
{devices.map((device, index) => (
|
||||||
|
<div key={index} className={styles.device_card}>
|
||||||
|
<div className={styles.device_name}>{device.represent}</div>
|
||||||
|
<IconRssi height={14} level={device.rssi} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const DeviceList: FC = () => {
|
const DeviceList: FC = () => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.devices}>
|
<div className={styles.devices}>
|
||||||
<ScrollArea enableY></ScrollArea>
|
<ScrollArea enableY>
|
||||||
|
<div className={styles.devices_list_layout}>
|
||||||
|
<AvailableDevices />
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user