Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,648 changes: 893 additions & 2,755 deletions package-lock.json

Large diffs are not rendered by default.

41 changes: 20 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,23 @@
"distDir": "out"
},
"dependencies": {
"@radix-ui/react-accordion": "^1.2.0",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-hover-card": "^1.1.1",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-radio-group": "^1.1.3",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slider": "^1.1.2",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.1.0",
"@radix-ui/react-toggle": "^1.1.0",
"@radix-ui/react-toggle-group": "^1.1.0",
"@radix-ui/react-tooltip": "^1.0.7",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-avatar": "^1.1.11",
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-hover-card": "^1.1.15",
"@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-radio-group": "^1.3.8",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slider": "^1.3.6",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-toggle": "^1.1.10",
"@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.8",
"@types/p5": "^1.7.6",
"@types/w3c-web-serial": "^1.0.6",
"class-variance-authority": "^0.7.0",
Expand All @@ -41,17 +41,16 @@
"html2canvas": "^1.4.1",
"jszip": "^3.10.1",
"lucide-react": "^0.460.0",
"next": "^15.3.3",
"next": "^16.0.3",
"next-pwa": "^5.6.0",
"next-themes": "^0.3.0",
"react": "^18",
"react-dom": "^18",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-icons": "^5.3.0",
"smoothie": "^1.36.1",
"sonner": "^1.5.0",
"tailwind-merge": "^2.3.0",
"tailwindcss-animate": "^1.0.7",
"tailwindcss-textshadow": "^2.1.3",
"uuid": "^11.0.3",
"webgl-plot": "^0.7.2"
},
Expand Down
26 changes: 26 additions & 0 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "Chords",
"short_name": "Chords",
"start_url": "/",
"display": "standalone",
"icons": [
{
"src": "/chords-logo-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/chords-logo-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"screenshots": [
{
"src": "/screenshot-chords.png",
"sizes": "1280x720",
"type": "image/png",
"form_factor": "wide"
}
]
}
Binary file removed src/app/favicon.ico
Binary file not shown.
5 changes: 2 additions & 3 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,8 @@ export default function RootLayout({
}>) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<link rel="manifest" href={`${basePath}/manifest.json`} /> {/* ✅ Dynamic manifest */}
</head>
{/* ✅ Dynamic manifest */}
<head><link rel="manifest" href={`${basePath}/manifest.json`} /></head>
<body
className={cn(
lobsterTwo.variable,
Expand Down
3 changes: 2 additions & 1 deletion src/app/npg-lite/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,6 @@ const NPG_Ble = () => {

const toggleChannel = (channelIndex: number) => {
setSelectedChannels((prevSelected) => {
setManuallySelected(true);
const updatedChannels = prevSelected.includes(channelIndex)
? prevSelected.filter((ch) => ch !== channelIndex)
: [...prevSelected, channelIndex];
Expand All @@ -799,6 +798,8 @@ const NPG_Ble = () => {

return sortedChannels;
});

setManuallySelected(true);
};


Expand Down
10 changes: 5 additions & 5 deletions src/components/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const Canvas = forwardRef(
ref
) => {
const { theme } = useTheme();
let previousCounter: number | null = null; // Variable to store the previous counter value for loss detection
const previousCounterRef = useRef<number | null>(null); // Variable to store the previous counter value for loss detection
const canvasContainerRef = useRef<HTMLDivElement>(null);
const [numChannels, setNumChannels] = useState<number>(selectedChannels.length);
const dataPointCountRef = useRef<number>(2000); // To track the calculated value
Expand Down Expand Up @@ -165,17 +165,17 @@ const Canvas = forwardRef(
processIncomingData(data);
updatePlots(data, Zoom);
}
if (previousCounter !== null) {
if (previousCounterRef.current !== null) {
// If there was a previous counter value
const expectedCounter: number = (previousCounter + 1) % 256; // Calculate the expected counter value
const expectedCounter: number = (previousCounterRef.current + 1) % 256; // Calculate the expected counter value
if (data[0] !== expectedCounter) {
// Check for data loss by comparing the current counter with the expected counter
console.warn(
`Data loss detected in canvas! Previous counter: ${previousCounter}, Current counter: ${data[0]}`
`Data loss detected in canvas! Previous counter: ${previousCounterRef.current}, Current counter: ${data[0]}`
);
}
}
previousCounter = data[0]; // Update the previous counter with the current counter
previousCounterRef.current = data[0]; // Update the previous counter with the current counter
},
}),
[Zoom, numChannels, timeBase]
Expand Down
47 changes: 32 additions & 15 deletions src/components/Connection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,8 @@ const Connection: React.FC<ConnectionProps> = ({


const toggleChannel = (channelIndex: number) => {
// Mark as manually selected and update selectedChannels
setSelectedChannels((prevSelected) => {
setManuallySelected(true);
const updatedChannels = prevSelected.includes(channelIndex)
? prevSelected.filter((ch) => ch !== channelIndex)
: [...prevSelected, channelIndex];
Expand All @@ -292,24 +292,29 @@ const Connection: React.FC<ConnectionProps> = ({
sortedChannels.push(1);
}

// Retrieve saved devices from localStorage
const savedPorts = JSON.parse(localStorage.getItem('savedDevices') || '[]');
const portInfo = portRef.current?.getInfo();

if (portInfo) {
const deviceIndex = savedPorts.findIndex(
(saved: SavedDevice) => saved.deviceName === devicenameref.current
);
// Retrieve saved devices from localStorage and persist selection
try {
const savedPorts = JSON.parse(localStorage.getItem('savedDevices') || '[]');
const portInfo = portRef.current?.getInfo();

if (deviceIndex !== -1) {
savedPorts[deviceIndex].selectedChannels = sortedChannels;
localStorage.setItem('savedDevices', JSON.stringify(savedPorts));
if (portInfo) {
const deviceIndex = savedPorts.findIndex(
(saved: SavedDevice) => saved.deviceName === devicenameref.current
);

if (deviceIndex !== -1) {
savedPorts[deviceIndex].selectedChannels = sortedChannels;
localStorage.setItem('savedDevices', JSON.stringify(savedPorts));
}
}
} catch (e) {
console.warn('Failed to persist selected channels:', e);
}

return sortedChannels;
});

setManuallySelected(true);
};

// Handle right arrow click (reset count and disable button if needed)
Expand Down Expand Up @@ -357,11 +362,21 @@ const Connection: React.FC<ConnectionProps> = ({
if (!workerRef.current) {
initializeWorker();
}
setCanvasCount(selectedChannels.length)
// Update parent canvasCount only when it differs to avoid unnecessary rerenders
const newCount = selectedChannels.length;
if (typeof setCanvasCount === 'function' && newCount !== canvasCount) {
setCanvasCount(newCount);
}

// Send canvasCount independently to the worker
workerRef.current?.postMessage({ action: 'setCanvasCount', canvasCount: canvasElementCountRef.current });
};
setCanvasCountInWorker(canvasElementCountRef.current);

// Run the canvas count sync after render (and when selectedChannels change)
useEffect(() => {
setCanvasCountInWorker(canvasElementCountRef.current);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedChannels.length]);

const setSelectedChannelsInWorker = (selectedChannels: number[]) => {
if (!workerRef.current) {
Expand Down Expand Up @@ -412,8 +427,10 @@ const Connection: React.FC<ConnectionProps> = ({

if (zipBlob) {
saveAs(zipBlob, 'ChordsWeb.zip');
toast.success("Data successfully downloaded as ZIP.");
} else if (error) {
console.error(error);
toast.error(`Error while creating ZIP: ${error}`);
}
};
}
Expand Down Expand Up @@ -1537,7 +1554,7 @@ const Connection: React.FC<ConnectionProps> = ({
<div className="flex gap-3 items-center justify-center">
{/* Connection button with tooltip */}
<TooltipProvider>
<Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
Expand Down
25 changes: 13 additions & 12 deletions src/components/Contributors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from "../components/ui/card";
import { Separator } from "../components/ui/separator";
import { Avatar, AvatarFallback, AvatarImage } from "../components/ui/avatar";
import { Dialog, DialogContent, DialogTrigger } from "../components/ui/dialog";
import { Dialog, DialogContent, DialogTrigger, DialogTitle } from "../components/ui/dialog";
import { CircleAlert } from "lucide-react";
import { Button } from "../components/ui/button";
import Link from "next/link";
Expand Down Expand Up @@ -62,22 +62,23 @@ const contributors = [
export default function Contributors() {
return (
<Dialog>
<DialogTrigger>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<DialogTrigger asChild>
<Button variant="ghost" size="icon">
<CircleAlert className="h-5 w-5" />
<span className="sr-only">View Contributors</span>
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Contributors</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</DialogTrigger>
</DialogTrigger>
</TooltipTrigger>
<TooltipContent>
<p>Contributors</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<DialogContent className="sm:max-w-[425px] md:max-w-[570px] lg:max-w-[650px]">
<DialogTitle className="sr-only">Contributors</DialogTitle>
<Card className="border-none">
<CardHeader className="p-0 mb-2">
<CardTitle className="font-bold items-center gap-2 flex mb-1">
Expand Down
8 changes: 4 additions & 4 deletions src/components/DataPass.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const DataPass = () => {
const [channelCount, setChannelCount] = useState<number>(1); // Number of channels
const canvasRef = useRef<any>(null); // Create a ref for the Canvas component
const [selectedChannels, setSelectedChannels] = useState<number[]>([1]);
let previousCounter: number | null = null; // Variable to store the previous counter value for loss detection
const previousCounter = useRef<number | null>(null); // Variable to store the previous counter value for loss detection
const [Zoom, SetZoom] = useState<number>(1); // Number of canvases
const [currentSnapshot, SetCurrentSnapshot] = useState<number>(0); // Number of canvases
const pauseRef = useRef<boolean>(true);
Expand All @@ -33,17 +33,17 @@ const DataPass = () => {
if (canvasRef.current) {
canvasRef.current.updateData(data); // Assuming data is the new data to be displayed
}
if (previousCounter !== null) {
if (previousCounter.current !== null) {
// If there was a previous counter value
const expectedCounter: number = (previousCounter + 1) % 256; // Calculate the expected counter value
const expectedCounter: number = (previousCounter.current + 1) % 256; // Calculate the expected counter value
if (data[0] !== expectedCounter) {
// Check for data loss by comparing the current counter with the expected counter
console.warn(
`Data loss detected in datapass! Previous counter: ${previousCounter}, Current counter: ${data[0]}`
);
}
}
previousCounter = data[0]; // Update the previous counter with the current counter
previousCounter.current = data[0]; // Update the previous counter with the current counter
}, []);
return (
<div className="flex flex-col h-screen m-0 p-0 bg-g ">
Expand Down
8 changes: 5 additions & 3 deletions src/components/FFT.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const FFT = forwardRef(
}
`;

let samplesReceived = 0;
const samplesReceivedRef = useRef<number>(0);
class SmoothingFilter {
private bufferSize: number;
private circularBuffers: number[][];
Expand Down Expand Up @@ -202,8 +202,8 @@ const FFT = forwardRef(
if (fftBufferRef.current[i].length > fftSize) {
fftBufferRef.current[i].shift();
}
samplesReceived++;
if (samplesReceived % sampleupdateref.current === 0) {
samplesReceivedRef.current++;
if (samplesReceivedRef.current % sampleupdateref.current === 0) {
const processedBuffer = fftBufferRef.current[i].slice(0, fftSize);
const floatInput = new Float32Array(processedBuffer);
const fftMags = fftProcessor.computeMagnitudes(floatInput);
Expand All @@ -215,6 +215,8 @@ const FFT = forwardRef(
newData[i] = smoothedMags;
return newData;
});
// prevent overflow
if (samplesReceivedRef.current > 1e9) samplesReceivedRef.current = 0;
}
}
},
Expand Down
10 changes: 6 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
Expand All @@ -35,9 +35,11 @@
"**/*.ts",
".next/types/**/*.ts",
"**/*.tsx",
"out/types/**/*.ts"
, "scripts/generateManifest.mjs" ],
"out/types/**/*.ts",
"scripts/generateManifest.mjs",
".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}
}
Loading
Loading