From 740bee6d532ebbcd05727ba7221cc4543883ce82 Mon Sep 17 00:00:00 2001 From: Aman Maheshwari Date: Fri, 13 Dec 2024 12:43:44 +0530 Subject: [PATCH 01/11] Add board Arduino Giga WiFi --- src/components/Canvas.tsx | 6 ++++-- src/components/DataPass.tsx | 2 +- src/components/boards.ts | 5 +++++ src/components/filters.tsx | 5 ++++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/components/Canvas.tsx b/src/components/Canvas.tsx index 8ee6073..93ac24c 100644 --- a/src/components/Canvas.tsx +++ b/src/components/Canvas.tsx @@ -61,6 +61,8 @@ const Canvas = forwardRef( return samplingRate * 4; case "fourteen": return samplingRate * 4; + case "sixteen": + return samplingRate * 4; default: return 0; // Or any other fallback value you'd like } @@ -82,7 +84,7 @@ const Canvas = forwardRef( if (array3DRef.current[activebuffer.current][i].length >= numX) { array3DRef.current[activebuffer.current][i] = []; } - array3DRef.current[activebuffer.current][i].push(incomingData[i+1]); + array3DRef.current[activebuffer.current][i].push(incomingData[i + 1]); if (array3DRef.current[activebuffer.current][i].length < numX && !pauseRef.current) { array3DRef.current[activebuffer.current][i] = []; @@ -289,7 +291,7 @@ const Canvas = forwardRef( // Use a separate sweep position for each line currentSweepPos.current[i] = sweepPositions.current[i]; // Plot the new data at the current sweep position - line.setY(currentSweepPos.current[i] % line.numPoints, data[i+1]); + line.setY(currentSweepPos.current[i] % line.numPoints, data[i + 1]); // Clear the next point to create a gap (optional, for visual effect) const clearPosition = (currentSweepPos.current[i] + (numX / 100)) % line.numPoints; diff --git a/src/components/DataPass.tsx b/src/components/DataPass.tsx index e1b9254..f654f53 100644 --- a/src/components/DataPass.tsx +++ b/src/components/DataPass.tsx @@ -6,7 +6,7 @@ import React, { useState, useCallback, useRef } from "react"; import Canvas from "./Canvas"; import Navbar from "./Navbar"; // Import the Navbar -export type BitSelection = "ten" | "twelve" | "fourteen" | "auto"; +export type BitSelection = "ten" | "twelve" | "fourteen" | "sixteen" | "auto"; const DataPass = () => { const [selectedBits, setSelectedBits] = useState("auto"); // Selected bits diff --git a/src/components/boards.ts b/src/components/boards.ts index 75c0c44..53b4e7a 100644 --- a/src/components/boards.ts +++ b/src/components/boards.ts @@ -39,4 +39,9 @@ export const BoardsList = Object.freeze([ field_pid: "192", bits: "twelve", }, + { + name: "Arduino Giga WiFi", + field_pid: "614", + bits: "sixteen", + }, ]); diff --git a/src/components/filters.tsx b/src/components/filters.tsx index 8d53dbb..a2d4ebc 100644 --- a/src/components/filters.tsx +++ b/src/components/filters.tsx @@ -46,7 +46,8 @@ export class EXGFilter { // function to apply the setSample(sample: string): void { this.sample = sample; - this.bitsPoints = Math.pow(2, + this.bitsPoints = Math.pow(2, + sample === "sixteen" ?16 : sample === "fourteen" ? 14 : sample === "twelve" ? 12 : 10 ); // Adjust according to your ADC resolution @@ -59,6 +60,7 @@ export class EXGFilter { let chData=0; switch (this.sample) { //samplerate 500Hz + case "sixteen": case "fourteen": case "twelve": // 500Hz switch (type) { @@ -178,6 +180,7 @@ export class Notch { if(!type) return input; let output = input; switch (this.sample) { + case "sixteen" : case "fourteen": // 500Hz case "twelve": // 500Hz switch (type) { From 2720e688ded90be29e7363cc73f80ee0f62143d0 Mon Sep 17 00:00:00 2001 From: Aman Maheshwari Date: Sat, 14 Dec 2024 11:57:33 +0530 Subject: [PATCH 02/11] Added webworker --- next.config.mjs | 18 +- package.json | 1 + src/app/page.tsx | 2 + src/components/Connection.tsx | 469 ++++++++++++--------- src/components/LandingComp/HeadSection.tsx | 4 +- src/components/boards.ts | 2 +- workers/indexedDBWorker.ts | 75 ++++ 7 files changed, 353 insertions(+), 218 deletions(-) create mode 100644 workers/indexedDBWorker.ts diff --git a/next.config.mjs b/next.config.mjs index 1a1c050..fd4bf88 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,7 +1,7 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { +// next.config.mjs +export default { reactStrictMode: true, - output: 'export', // This is key for static export + output: 'export', images: { unoptimized: true, remotePatterns: [ @@ -11,6 +11,14 @@ const nextConfig = { }, ], }, + webpack(config, { isServer }) { + // If this is the server-side bundle, we don’t need to process worker files + if (!isServer) { + config.module.rules.push({ + test: /\.worker\.(js|ts)$/, + use: { loader: 'worker-loader' }, + }); + } + return config; + }, }; -/* module.exports = nextConfig*/ -export default nextConfig; diff --git a/package.json b/package.json index 194b837..f618fac 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "Chords", "version": "2.3.0a", "private": true, + "type": "module", "scripts": { "dev": "next dev", "build": "next build", diff --git a/src/app/page.tsx b/src/app/page.tsx index ba15632..96de939 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,3 +1,5 @@ +'use client'; + import React from "react"; import Navbar from "../components/Navbar"; import { Skeleton } from "../components/ui/skeleton"; diff --git a/src/components/Connection.tsx b/src/components/Connection.tsx index 923dd54..65f2a9e 100644 --- a/src/components/Connection.tsx +++ b/src/components/Connection.tsx @@ -115,7 +115,7 @@ const Connection: React.FC = ({ const recordingBuffers = Array(NUM_BUFFERS) .fill(null) .map(() => [] as number[][]); - const fillingindex = useRef(0); // Initialize useRef with 0 + const fillingindex = useRef(0); // Initialize useRef with 0 let activeBufferIndex = 0; const togglePause = () => { @@ -124,24 +124,24 @@ const Connection: React.FC = ({ onPauseChange(newPauseState); // Notify parent about the change SetcurrentSnapshot(0); setClickCount(0); - + }; const increaseCanvas = () => { - if (canvasCount < (detectedBitsRef.current=="twelve"?3:6)) { + if (canvasCount < (detectedBitsRef.current == "twelve" ? 3 : 6)) { setCanvasCount(canvasCount + 1); // Increase canvas count up to 6 } }; const [clickCount, setClickCount] = useState(0); // Track how many times the left arrow is clicked - const enabledClicks = (snapShotRef.current?.filter(Boolean).length ?? 0)-1; + const enabledClicks = (snapShotRef.current?.filter(Boolean).length ?? 0) - 1; // Enable/Disable left arrow button const handlePrevSnapshot = () => { if (clickCount < enabledClicks) { setClickCount(clickCount + 1); } - + if (currentSnapshot < 4) { SetcurrentSnapshot(currentSnapshot + 1); } @@ -149,15 +149,15 @@ const Connection: React.FC = ({ // Handle right arrow click (reset count and disable button if needed) const handleNextSnapshot = () => { - if (clickCount>0) { - setClickCount(clickCount-1); // Reset count after right arrow click + if (clickCount > 0) { + setClickCount(clickCount - 1); // Reset count after right arrow click } if (currentSnapshot > 0) { SetcurrentSnapshot(currentSnapshot - 1); } }; - + const decreaseCanvas = () => { if (canvasCount > 1) { @@ -165,11 +165,11 @@ const Connection: React.FC = ({ } }; const toggleShowAllChannels = () => { - if (canvasCount === (detectedBitsRef.current=="twelve"?3:6)) { + if (canvasCount === (detectedBitsRef.current == "twelve" ? 3 : 6)) { setCanvasCount(1); // If canvasCount is 6, reduce it to 1 setShowAllChannels(false); } else { - setCanvasCount(detectedBitsRef.current=="twelve"?3:6); // Otherwise, show all 6 canvases + setCanvasCount(detectedBitsRef.current == "twelve" ? 3 : 6); // Otherwise, show all 6 canvases setShowAllChannels(true); } }; @@ -195,7 +195,7 @@ const Connection: React.FC = ({ } }; - + useEffect(() => { canvasnumbersRef.current = canvasCount; // Sync the ref with the state }, [canvasCount]); @@ -218,6 +218,40 @@ const Connection: React.FC = ({ } }; + ////////////////////////////////// + const workerRef = useRef(null); + + const initializeWorker = () => { + if (!workerRef.current) { + workerRef.current = new Worker(new URL('../../workers/indexedDBWorker.ts', import.meta.url), { + type: 'module', + }); + } + }; + + const processBuffer = async (bufferIndex: number) => { + if (!workerRef.current) { + initializeWorker(); + } + + // If the buffer is empty, return early + if (recordingBuffers[bufferIndex].length === 0) return; + + const data = recordingBuffers[bufferIndex]; + const filename = currentFilenameRef.current; + + if (filename) { + // Check if the record already exists + workerRef.current?.postMessage({ action: 'checkExistence', filename }); + writeToIndexedDB(data, filename); + } + }; + + const writeToIndexedDB = (data: number[][], filename: string) => { + workerRef.current?.postMessage({ action: 'write', data, filename }); + }; + ////////////////////////////////////////// + const handleCustomTimeChange = (e: React.ChangeEvent) => { // Function to handle the custom time input change const value = e.target.value.replace(/[^0-9]/g, ""); @@ -306,13 +340,13 @@ const Connection: React.FC = ({ // Check for specific usbProductId 29987 and set baud rate if (usbProductId === 29987) { baudRate = 115200; - + } const existingDevice = savedPorts.find(saved => saved.usbVendorId === usbVendorId && saved.usbProductId === usbProductId ); - + if (!existingDevice) { savedPorts.push({ usbVendorId, @@ -405,13 +439,13 @@ const Connection: React.FC = ({ readerRef.current = null; } } - + // Close port if (portRef.current.readable) { await portRef.current.close(); } portRef.current = null; - + toast("Disconnected from device", { action: { label: "Reconnect", @@ -491,8 +525,8 @@ const Connection: React.FC = ({ // Function to read data from a connected device and process it const readData = async (): Promise => { const HEADER_LENGTH = 3; // Length of the packet header - const NUM_CHANNELS = detectedBitsRef.current=="twelve"?3:6; // Number of channels in the data packet - const PACKET_LENGTH = detectedBitsRef.current=="twelve"?10:16; // Total length of each packet + const NUM_CHANNELS = detectedBitsRef.current == "twelve" ? 3 : 6; // Number of channels in the data packet + const PACKET_LENGTH = detectedBitsRef.current == "twelve" ? 10 : 16; // Total length of each packet const SYNC_BYTE1 = 0xc7; // First synchronization byte to identify the start of a packet const SYNC_BYTE2 = 0x7c; // Second synchronization byte const END_BYTE = 0x01; // End byte to signify the end of a packet @@ -566,14 +600,14 @@ const Connection: React.FC = ({ datastream(channelData); // Pass the channel data to the LineData function for further processing if (isRecordingRef.current) { const channeldatavalues = channelData - .slice(0, canvasnumbersRef.current + 1) - .map((value) => (value !== undefined ? value : null)) - .filter((value): value is number => value !== null); // Filter out null values + .slice(0, canvasnumbersRef.current + 1) + .map((value) => (value !== undefined ? value : null)) + .filter((value): value is number => value !== null); // Filter out null values // Check if recording is enabled - recordingBuffers[activeBufferIndex][fillingindex.current]=channeldatavalues; + recordingBuffers[activeBufferIndex][fillingindex.current] = channeldatavalues; // activeBuffer.push(channeldatavalues); // Store the channel data in the recording buffer - - if (fillingindex.current >= MAX_BUFFER_SIZE-1) { + + if (fillingindex.current >= MAX_BUFFER_SIZE - 1) { processBuffer(activeBufferIndex); activeBufferIndex = (activeBufferIndex + 1) % NUM_BUFFERS; } @@ -635,114 +669,114 @@ const Connection: React.FC = ({ }; - // Function to process a buffer and save it to IndexedDB - const processBuffer = async (bufferIndex: number) => { - - // If the buffer is empty, return early - if (recordingBuffers[bufferIndex].length === 0) return; - - // Attempt to write data to IndexedDB - if (currentFilenameRef.current) { - const success = await writeToIndexedDB(recordingBuffers[bufferIndex]); - if (success) { - // Clear the buffer after successful write - } else { - console.error("Failed to save buffer to IndexedDB. Retrying..."); - } - } else { - console.log("Filename is not set"); - } - }; - let dbInstance: IDBDatabase | null = null; + // // Function to process a buffer and save it to IndexedDB + // const processBuffer = async (bufferIndex: number) => { + + // // If the buffer is empty, return early + // if (recordingBuffers[bufferIndex].length === 0) return; + + // // Attempt to write data to IndexedDB + // if (currentFilenameRef.current) { + // const success = await writeToIndexedDB(recordingBuffers[bufferIndex]); + // if (success) { + // // Clear the buffer after successful write + // } else { + // console.error("Failed to save buffer to IndexedDB. Retrying..."); + // } + // } else { + // console.log("Filename is not set"); + // } + // }; + // let dbInstance: IDBDatabase | null = null; const existingRecordRef = useRef(undefined); - const getDBInstance = async (): Promise => { - if (!dbInstance) { - dbInstance = await openIndexedDB(); - console.log(dbInstance); - } - return dbInstance; - }; - - const writeToIndexedDB = useCallback( - async (data: number[][]): Promise => { - if (!indexedDB) { - console.error("IndexedDB is not supported in this browser."); - return false; - } - - if (!currentFilenameRef.current) { - console.error("Filename is not set. Cannot write to IndexedDB."); - return false; - } - - // Use a ref to track if we already checked for the record - if (!existingRecordRef.current) { - try { - const db = await getDBInstance(); // Reuse existing connection - const tx = db.transaction("ChordsRecordings", "readwrite"); - const store = tx.objectStore("ChordsRecordings"); - - // Check if record exists and cache the result - const existingRecord = await new Promise( - (resolve, reject) => { - const getRequest = store.get(currentFilenameRef.current!); - getRequest.onsuccess = () => resolve(getRequest.result); - getRequest.onerror = () => reject(getRequest.error); - } - ); - - // Cache the record in a ref for later use - existingRecordRef.current = existingRecord; - - } catch (error) { - console.error("Error checking for existing record:", error); - return false; - } - } - - // Now use the cached existingRecordRef - const existingRecord = existingRecordRef.current; - - try { - const db = await getDBInstance(); // Reuse existing connection - const tx = db.transaction("ChordsRecordings", "readwrite"); - const store = tx.objectStore("ChordsRecordings"); - - if (existingRecord) { - // If the record exists, append data to it - existingRecord.content.push(...data); - await new Promise((resolve, reject) => { - const putRequest = store.put(existingRecord); - putRequest.onsuccess = () => resolve(); - putRequest.onerror = () => reject(putRequest.error); - }); - - // Data appended to existing record - } else { - // If no record exists, create a new record and save data - const newRecord = { - filename: currentFilenameRef.current!, - content: [...data], - }; - - await new Promise((resolve, reject) => { - const putRequest = store.put(newRecord); - putRequest.onsuccess = () => resolve(); - putRequest.onerror = () => reject(putRequest.error); - }); - - // New record created and data saved - } - - return true; - } catch (error) { - console.error("Error writing to IndexedDB:", error); - return false; - } - }, - [canvasCount] - ); - + // const getDBInstance = async (): Promise => { + // if (!dbInstance) { + // dbInstance = await openIndexedDB(); + // console.log(dbInstance); + // } + // return dbInstance; + // }; + + // const writeToIndexedDB = useCallback( + // async (data: number[][]): Promise => { + // if (!indexedDB) { + // console.error("IndexedDB is not supported in this browser."); + // return false; + // } + + // if (!currentFilenameRef.current) { + // console.error("Filename is not set. Cannot write to IndexedDB."); + // return false; + // } + + // // Use a ref to track if we already checked for the record + // if (!existingRecordRef.current) { + // try { + // const db = await getDBInstance(); // Reuse existing connection + // const tx = db.transaction("ChordsRecordings", "readwrite"); + // const store = tx.objectStore("ChordsRecordings"); + + // // Check if record exists and cache the result + // const existingRecord = await new Promise( + // (resolve, reject) => { + // const getRequest = store.get(currentFilenameRef.current!); + // getRequest.onsuccess = () => resolve(getRequest.result); + // getRequest.onerror = () => reject(getRequest.error); + // } + // ); + + // // Cache the record in a ref for later use + // existingRecordRef.current = existingRecord; + + // } catch (error) { + // console.error("Error checking for existing record:", error); + // return false; + // } + // } + + // // Now use the cached existingRecordRef + // const existingRecord = existingRecordRef.current; + + // try { + // const db = await getDBInstance(); // Reuse existing connection + // const tx = db.transaction("ChordsRecordings", "readwrite"); + // const store = tx.objectStore("ChordsRecordings"); + + // if (existingRecord) { + // // If the record exists, append data to it + // existingRecord.content.push(...data); + // await new Promise((resolve, reject) => { + // const putRequest = store.put(existingRecord); + // putRequest.onsuccess = () => resolve(); + // putRequest.onerror = () => reject(putRequest.error); + // }); + + // // Data appended to existing record + // } else { + // // If no record exists, create a new record and save data + // const newRecord = { + // filename: currentFilenameRef.current!, + // content: [...data], + // }; + + // await new Promise((resolve, reject) => { + // const putRequest = store.put(newRecord); + // putRequest.onsuccess = () => resolve(); + // putRequest.onerror = () => reject(putRequest.error); + // }); + + // // New record created and data saved + // } + + // return true; + // } catch (error) { + // console.error("Error writing to IndexedDB:", error); + // return false; + // } + // }, + // [canvasCount] + // ); + // Function to handle the recording process const handleRecord = async () => { if (isRecordingRef.current) { @@ -804,45 +838,45 @@ const Connection: React.FC = ({ }; // Function to initialize the IndexedDB and return a promise with the database instance - const openIndexedDB = async (): Promise => { - return new Promise((resolve, reject) => { - // Open a connection to the IndexedDB database - const request = indexedDB.open("ChordsRecordings", 2); // Update version if schema changes - - request.onupgradeneeded = (event) => { - const db = (event.target as IDBOpenDBRequest).result; - - switch (event.oldVersion) { - case 0: // Database doesn't exist, create initial schema - const store = db.createObjectStore("ChordsRecordings", { - keyPath: "filename", - }); - store.createIndex("filename", "filename", { unique: true }); - break; - - case 1: // Upgrade from version 1 to 2 - const transaction = request.transaction; - if (transaction) { - const existingStore = transaction.objectStore("ChordsRecordings"); - existingStore.createIndex("filename", "filename", { unique: true }); - } - break; - - default: - console.warn("No schema updates for this version."); - } - }; - - request.onsuccess = (event) => { - const db = (event.target as IDBOpenDBRequest).result; - resolve(db); // Resolve the promise with the database instance - }; - - request.onerror = () => { - reject(request.error); // Reject the promise with the error - }; - }); - }; + // const openIndexedDB = async (): Promise => { + // return new Promise((resolve, reject) => { + // // Open a connection to the IndexedDB database + // const request = indexedDB.open("ChordsRecordings", 2); // Update version if schema changes + + // request.onupgradeneeded = (event) => { + // const db = (event.target as IDBOpenDBRequest).result; + + // switch (event.oldVersion) { + // case 0: // Database doesn't exist, create initial schema + // const store = db.createObjectStore("ChordsRecordings", { + // keyPath: "filename", + // }); + // store.createIndex("filename", "filename", { unique: true }); + // break; + + // case 1: // Upgrade from version 1 to 2 + // const transaction = request.transaction; + // if (transaction) { + // const existingStore = transaction.objectStore("ChordsRecordings"); + // existingStore.createIndex("filename", "filename", { unique: true }); + // } + // break; + + // default: + // console.warn("No schema updates for this version."); + // } + // }; + + // request.onsuccess = (event) => { + // const db = (event.target as IDBOpenDBRequest).result; + // resolve(db); // Resolve the promise with the database instance + // }; + + // request.onerror = () => { + // reject(request.error); // Reject the promise with the error + // }; + // }); + // }; // Function to delete files by filename const deleteFilesByFilename = async (filename: string) => { @@ -961,15 +995,30 @@ const Connection: React.FC = ({ toast.error("An unexpected error occurred. Please try again."); } }; + const openIndexedNDB = async (): Promise => { + return new Promise((resolve, reject) => { + const request = indexedDB.open("ChordsRecordings", 2); + + request.onupgradeneeded = (event) => { + const db = (event.target as IDBOpenDBRequest).result; + const store = db.createObjectStore("ChordsRecordings", { + keyPath: "filename", + }); + store.createIndex("filename", "filename", { unique: true }); + }; + + request.onsuccess = (event) => resolve((event.target as IDBOpenDBRequest).result); + request.onerror = (event) => reject((event.target as IDBOpenDBRequest).error); + }); + }; // Function to get all data from IndexedDB const getAllDataFromIndexedDB = async (): Promise => { try { - const db = await openIndexedDB(); + const db = await openIndexedNDB(); const tx = db.transaction(["ChordsRecordings"], "readonly"); const store = tx.objectStore("ChordsRecordings"); const request = store.getAll(); - return new Promise((resolve, reject) => { request.onsuccess = () => { const data = request.result.map((item: any, index: number) => ({ @@ -1060,7 +1109,7 @@ const Connection: React.FC = ({ const saveAllDataAsZip = async () => { try { // Open IndexedDB - const db = await openIndexedDB(); + const db = await openIndexedNDB(); const tx = db.transaction("ChordsRecordings", "readonly"); const store = tx.objectStore("ChordsRecordings"); @@ -1098,13 +1147,13 @@ const Connection: React.FC = ({ - - return ( + + return (
{/* Left-aligned section */}
- {isRecordingRef.current && ( + {isRecordingRef.current && (
@@ -1248,7 +1297,7 @@ const Connection: React.FC = ({ - - - - - - -

- {isDisplay ? "Pause Data Display" : "Resume Data Display"} -

-
-
-
- + + + + + + + + +

+ {isDisplay ? "Pause Data Display" : "Resume Data Display"} +

+
+
+
+
)} {/* Record button with tooltip */} @@ -1703,14 +1752,14 @@ const Connection: React.FC = ({

- {canvasCount >= (detectedBitsRef.current=="twelve"?3:6) + {canvasCount >= (detectedBitsRef.current == "twelve" ? 3 : 6) ? "Maximum Channels Reached" : "Increase Channel"}

diff --git a/src/components/LandingComp/HeadSection.tsx b/src/components/LandingComp/HeadSection.tsx index ad4b07a..df35fe8 100644 --- a/src/components/LandingComp/HeadSection.tsx +++ b/src/components/LandingComp/HeadSection.tsx @@ -96,14 +96,14 @@ const HeadSection: React.FC = () => { fill="none" className="stroke-gray-600" - stroke-width="2" + strokeWidth="2" d="m 0,151.91036 c 1.4089684,-1.39202 2.8179419,-2.78405 4.4681851,-4.13231 1.6502432,-1.34827 3.5416817,-2.65272 5.8528189,-3.58815 2.311136,-0.93544 5.041824,-1.50181 8.026352,-1.9935 2.984527,-0.49169 6.222708,-0.90867 8.694494,-0.94351 2.471786,-0.0348 4.177047,0.31246 6.199305,0.0836 2.022258,-0.2289 4.361387,-1.03398 6.832335,-1.86309 2.470949,-0.82911 5.073566,-1.6822 7.177224,-2.40615 2.103658,-0.72394 3.708237,-1.31869 5.762729,-1.5884 2.054492,-0.26971 4.558759,-0.21435 6.498614,-0.41988 1.939854,-0.20554 3.31519,-0.67193 4.602769,-1.82816 1.287578,-1.15623 2.487324,-3.0022 3.530011,-4.75273 1.042687,-1.75054 1.928253,-3.40553 2.930166,-5.06322 1.001914,-1.65768 2.120116,-3.31797 3.025582,-4.36086 0.905467,-1.0429 1.598146,-1.46835 2.340165,-1.38478 0.742018,0.0836 1.533331,0.67613 2.358804,1.80648 0.825474,1.13035 1.685057,2.7984 2.532417,4.6308 0.847361,1.8324 1.682448,3.82904 2.421924,5.5969 0.739476,1.76787 1.383299,3.30686 2.169375,4.95085 0.786076,1.64399 1.714361,3.39289 2.473003,4.77641 0.758643,1.38353 1.347608,2.40162 1.833436,3.04871 0.485827,0.64708 0.868495,0.92314 1.238392,0.75947 0.369896,-0.16366 0.727004,-0.76703 1.059198,-2.09126 0.332194,-1.32423 0.639456,-3.36923 0.928193,-6.1011 0.288738,-2.73188 0.558934,-6.15045 0.868146,-10.64747 0.309213,-4.49703 0.657424,-10.07222 0.926815,-14.56848 0.269391,-4.49626 0.459946,-7.91333 0.564546,-11.864862 0.1046,-3.951531 0.12324,-8.437265 0.24807,-12.319313 0.12483,-3.882048 0.355841,-7.160189 0.594626,-11.246823 0.238785,-4.086634 0.485328,-8.9815 0.868959,-15.227791 0.383631,-6.246291 0.904324,-13.843606 1.270866,-20.242696 0.366542,-6.399089 0.578914,-11.599592 0.825642,-15.273484 0.246728,-3.673892 0.527796,-5.820983 0.743951,-7.450531 0.216157,-1.629547 0.367387,-2.741464 0.700637,-2.697678 0.33326,0.04379 0.84851,1.24325 1.2553,3.918753 0.40679,2.675504 0.70509,6.826856 1.04777,11.706554 0.34268,4.879699 0.72972,10.487438 1.10576,17.957982 0.37604,7.470544 0.74105,16.803407 1.07762,23.817415 0.33657,7.014009 0.64468,11.708788 0.82928,17.391016 0.18459,5.682228 0.24566,12.351548 0.46814,17.257868 0.22247,4.90633 0.60634,8.04941 0.98347,14.22494 0.37714,6.17552 0.74752,15.38307 1.21736,22.10594 0.46984,6.72286 1.0391,10.9607 1.5022,14.53279 0.46309,3.57209 0.81999,6.47823 1.16662,8.36498 0.34663,1.88676 0.68298,2.75404 1.12462,3.00595 0.44163,0.25191 0.98851,-0.11155 1.55014,-1.28942 0.56162,-1.17787 1.13795,-3.17006 1.93868,-6.87995 0.80073,-3.7099 1.8258,-9.13725 2.80452,-13.56605 0.97872,-4.4288 1.91103,-7.85881 2.64362,-10.29296 0.73259,-2.43415 1.26542,-3.87232 1.8567,-4.82241 0.59128,-0.95008 1.24096,-1.41204 1.86394,-1.51639 0.62298,-0.10435 1.21922,0.1489 1.83281,0.44756 0.61359,0.29866 1.24449,0.64271 2.08275,0.52793 0.83825,-0.11477 1.8838,-0.68834 3.30454,-3.03162 1.42075,-2.34328 3.21659,-6.45608 4.97147,-10.99867 1.75487,-4.5426 3.46867,-9.5147 5.00259,-14.00225 1.53392,-4.487552 2.88786,-8.490284 3.84014,-11.102991 0.95227,-2.612708 1.50283,-3.835259 2.05443,-4.712306 0.5516,-0.877046 1.1042,-1.408539 1.69746,-1.334752 0.59325,0.07379 1.22712,0.752841 1.96808,3.003871 0.74096,2.25103 1.58897,6.073869 2.593,11.707598 1.00403,5.63373 2.16403,13.07798 3.08806,19.31281 0.92404,6.23483 1.61206,11.25988 2.21371,15.2664 0.60166,4.00651 1.11692,6.99427 1.75325,9.80203 0.63632,2.80776 1.39367,5.43538 1.97584,7.2456 0.58217,1.81022 0.98912,2.80296 1.47237,3.45171 0.48326,0.64874 1.04278,0.95346 1.63677,0.97115 0.594,0.0177 1.22243,-0.25167 2.1727,-1.24317 0.95027,-0.99151 2.22232,-2.7051 3.44483,-4.26899 1.22252,-1.56389 2.39544,-2.97799 3.40604,-3.97841 1.01059,-1.00043 1.85881,-1.58714 2.77056,-1.68394 0.91175,-0.0968 1.88699,0.29633 2.90814,0.44724 1.02115,0.15092 2.08817,0.0596 3.23285,-0.28694 1.14467,-0.34656 2.36694,-0.94838 3.30891,-1.56253 0.94197,-0.61415 1.60358,-1.24061 2.73305,-1.58523 1.12946,-0.34462 2.7267,-0.40738 4.59882,-0.45684 1.87212,-0.0495 4.01899,-0.0856 5.61794,-0.33548 1.59894,-0.24987 2.64985,-0.71344 4.05227,-1.34899 1.40243,-0.63555 3.15626,-1.44303 4.57184,-2.08836 1.41558,-0.64532 2.49284,-1.12845 3.50633,-1.17734 1.01349,-0.0489 1.96316,0.33645 2.80166,0.63525 0.8385,0.2988 1.56578,0.51103 2.44837,0.44262 0.88259,-0.0684 1.92045,-0.41748 3.38571,-1.34269 1.46526,-0.92521 3.35783,-2.4265 5.3355,-4.3712 1.97767,-1.9447 4.04031,-4.33268 5.83434,-6.78245 1.79402,-2.44977 3.31932,-4.96116 4.37436,-6.58675 1.05504,-1.62559 1.63977,-2.3653 2.36626,-2.17635 0.72648,0.18895 1.59468,1.30651 3.10385,4.57937 1.50918,3.27286 3.65924,8.70078 5.15171,12.31497 1.49246,3.61419 2.32727,5.41448 3.12153,6.78414 0.79427,1.36965 1.54795,2.30859 2.12408,2.69433 0.57613,0.38575 0.97468,0.21828 1.42355,-1.34404 0.44887,-1.56231 0.94803,-4.51936 1.31556,-7.8305 0.36753,-3.31114 0.60341,-6.97619 0.78225,-10.03692 0.17885,-3.06074 0.30064,-5.517 0.64367,-10.56359 0.34303,-5.04659 0.90729,-12.68316 1.39442,-22.294541 0.48713,-9.61138 0.89712,-21.196955 1.46027,-33.478869 0.56314,-12.281913 1.2794,-25.259415 1.86178,-33.139148 0.58239,-7.879733 1.03085,-10.661327 1.47898,-10.901076 0.44813,-0.239748 0.89588,2.062317 1.54612,8.734983 0.65023,6.672666 1.5029,17.71545 2.13378,27.18548 0.63089,9.47003 1.03996,17.36677 1.53719,28.534393 0.49724,11.167623 1.0826,25.605398 1.74802,38.164268 0.66541,12.55887 1.41083,23.23812 1.98819,30.44353 0.57737,7.2054 0.98665,10.9366 1.54054,13.67813 0.5539,2.74152 1.25237,4.49324 2.05864,4.40281 0.80627,-0.0904 1.72029,-2.02295 2.6288,-5.20942 0.9085,-3.18647 1.81143,-7.62665 3.10339,-12.69331 1.29196,-5.06666 2.97286,-10.75947 4.11884,-13.65377 1.14598,-2.8943 1.75697,-2.98997 2.8881,-3.31013 1.13112,-0.32016 2.7823,-0.86478 4.6565,-2.78114 1.87421,-1.91637 3.97131,-5.20432 6.4053,-10.96413 2.43398,-5.7598 5.2047,-13.99105 7.02612,-19.629221 1.82141,-5.63817 2.69342,-8.682969 3.47491,-10.608802 0.78148,-1.925834 1.47239,-2.732606 2.18342,-2.516723 0.71102,0.215884 1.44211,1.454392 2.5786,5.791765 1.13649,4.337374 2.6783,11.773291 3.65564,17.530481 0.97734,5.75718 1.39015,9.83531 1.95739,14.54295 0.56724,4.70763 1.28887,10.04447 1.91043,13.98867 0.62157,3.9442 1.14304,6.49556 1.65044,8.66736 0.5074,2.17179 1.0007,3.96389 1.61637,5.524 0.61567,1.56011 1.35368,2.88814 2.2153,3.39299 0.86163,0.50485 1.84681,0.1865 3.35108,-1.06931 1.50427,-1.25582 3.52753,-3.44901 5.62056,-5.21377 2.09304,-1.76475 4.25573,-3.10097 6.08898,-3.92807 1.83324,-0.82709 3.33693,-1.14501 5.23016,-0.94456 1.89323,0.20045 4.17588,0.91925 6.15206,1.00161 1.97618,0.0823 3.64579,-0.47173 5.13936,-1.09221 1.49356,-0.62047 2.811,-1.30729 4.1581,-1.79069 1.3471,-0.48339 2.72378,-0.76333 3.86259,-0.60563 1.13882,0.1577 2.0397,0.75302 3.5206,0.93945 1.4809,0.18643 3.54172,-0.036 5.14366,-0.47132 1.60194,-0.43528 2.74492,-1.08334 3.88793,-1.73141"> {/* */} {/* */} - + { + const { action, data, filename } = event.data; + + // Open IndexedDB + const db = await openIndexedDB(); + + switch (action) { + case 'write': + const success = await writeToIndexedDB(db, data, filename); + self.postMessage({ success }); + break; + + default: + self.postMessage({ error: 'Invalid action' }); + } + }; + + // Function to open IndexedDB + const openIndexedDB = async (): Promise => { + return new Promise((resolve, reject) => { + const request = indexedDB.open("ChordsRecordings", 2); + + request.onupgradeneeded = (event) => { + const db = (event.target as IDBOpenDBRequest).result; + const store = db.createObjectStore("ChordsRecordings", { + keyPath: "filename", + }); + store.createIndex("filename", "filename", { unique: true }); + }; + + request.onsuccess = (event) => resolve((event.target as IDBOpenDBRequest).result); + request.onerror = (event) => reject((event.target as IDBOpenDBRequest).error); + }); + }; + + // Function to write data to IndexedDB + const writeToIndexedDB = async (db: IDBDatabase, data: number[][], filename: string): Promise => { + return new Promise((resolve, reject) => { + const tx = db.transaction("ChordsRecordings", "readwrite"); + const store = tx.objectStore("ChordsRecordings"); + + const getRequest = store.get(filename); + + getRequest.onsuccess = () => { + const existingRecord = getRequest.result; + + if (existingRecord) { + existingRecord.content.push(...data); + const putRequest = store.put(existingRecord); + putRequest.onsuccess = () => resolve(true); + putRequest.onerror = () => reject(false); + } else { + const newRecord = { filename, content: [...data] }; + const putRequest = store.put(newRecord); + putRequest.onsuccess = () => resolve(true); + putRequest.onerror = () => reject(false); + } + }; + + getRequest.onerror = () => reject(false); + }); + }; + + // Function to check if a record exists in IndexedDB + const checkRecordExistence = async (db: IDBDatabase, filename: string): Promise => { + return new Promise((resolve) => { + const tx = db.transaction("ChordsRecordings", "readonly"); + const store = tx.objectStore("ChordsRecordings"); + const getRequest = store.get(filename); + + getRequest.onsuccess = () => resolve(!!getRequest.result); + getRequest.onerror = () => resolve(false); + }); + }; + \ No newline at end of file From 66e96eb86e0f1fb15f2fce40dfec93411f5bd99c Mon Sep 17 00:00:00 2001 From: Ritika Mishra Date: Sun, 15 Dec 2024 00:31:52 +0530 Subject: [PATCH 03/11] implemented web worker for indexeddb functions --- src/components/Connection.tsx | 284 +++++++--------------------------- workers/indexedDBWorker.ts | 109 ++++++++++++- 2 files changed, 166 insertions(+), 227 deletions(-) diff --git a/src/components/Connection.tsx b/src/components/Connection.tsx index 65f2a9e..53573f5 100644 --- a/src/components/Connection.tsx +++ b/src/components/Connection.tsx @@ -250,6 +250,65 @@ const Connection: React.FC = ({ const writeToIndexedDB = (data: number[][], filename: string) => { workerRef.current?.postMessage({ action: 'write', data, filename }); }; + + const getAllDataFromIndexedDB = async (): Promise => { + if (!workerRef.current) { + initializeWorker(); + } + + return new Promise((resolve, reject) => { + if (workerRef.current) { + workerRef.current.postMessage({ action: 'getAllData' }); + + workerRef.current.onmessage = (event) => { + if (event.data.allData) { + resolve(event.data.allData); + } else if (event.data.error) { + reject(event.data.error); + } + }; + + workerRef.current.onerror = (error) => { + reject(`Error in worker: ${error.message}`); + }; + } else { + reject('Worker is not initialized'); + } + }); + }; + + const saveAllDataAsZip = async () => { + try { + if (!workerRef.current) { + initializeWorker(); // Ensure the worker is initialized + } + + const canvasCount = 4; // Example value, modify as needed + workerRef.current?.postMessage({ action: 'saveAllDataAsZip', canvasCount }); + + return new Promise((resolve, reject) => { // Explicitly specify 'void' + if (workerRef.current) { + workerRef.current.onmessage = (event) => { + if (event.data.success) { + resolve(); // Resolving with no value + } else if (event.data.error) { + reject(event.data.error); + } + }; + + workerRef.current.onerror = (error) => { + reject(`Error in worker: ${error.message}`); + }; + } else { + reject("Worker is not initialized"); + } + }); + } catch (error) { + console.error("Error in saveAllDataAsZip function:", error); + throw error; + } + }; + ////////////////////////////////////////// const handleCustomTimeChange = (e: React.ChangeEvent) => { @@ -650,7 +709,6 @@ const Connection: React.FC = ({ } }; - const convertToCSV = (data: any[], canvasCount: number): string => { if (data.length === 0) return ""; @@ -668,115 +726,7 @@ const Connection: React.FC = ({ return [header.join(","), ...rows].join("\n"); }; - - // // Function to process a buffer and save it to IndexedDB - // const processBuffer = async (bufferIndex: number) => { - - // // If the buffer is empty, return early - // if (recordingBuffers[bufferIndex].length === 0) return; - - // // Attempt to write data to IndexedDB - // if (currentFilenameRef.current) { - // const success = await writeToIndexedDB(recordingBuffers[bufferIndex]); - // if (success) { - // // Clear the buffer after successful write - // } else { - // console.error("Failed to save buffer to IndexedDB. Retrying..."); - // } - // } else { - // console.log("Filename is not set"); - // } - // }; - // let dbInstance: IDBDatabase | null = null; const existingRecordRef = useRef(undefined); - // const getDBInstance = async (): Promise => { - // if (!dbInstance) { - // dbInstance = await openIndexedDB(); - // console.log(dbInstance); - // } - // return dbInstance; - // }; - - // const writeToIndexedDB = useCallback( - // async (data: number[][]): Promise => { - // if (!indexedDB) { - // console.error("IndexedDB is not supported in this browser."); - // return false; - // } - - // if (!currentFilenameRef.current) { - // console.error("Filename is not set. Cannot write to IndexedDB."); - // return false; - // } - - // // Use a ref to track if we already checked for the record - // if (!existingRecordRef.current) { - // try { - // const db = await getDBInstance(); // Reuse existing connection - // const tx = db.transaction("ChordsRecordings", "readwrite"); - // const store = tx.objectStore("ChordsRecordings"); - - // // Check if record exists and cache the result - // const existingRecord = await new Promise( - // (resolve, reject) => { - // const getRequest = store.get(currentFilenameRef.current!); - // getRequest.onsuccess = () => resolve(getRequest.result); - // getRequest.onerror = () => reject(getRequest.error); - // } - // ); - - // // Cache the record in a ref for later use - // existingRecordRef.current = existingRecord; - - // } catch (error) { - // console.error("Error checking for existing record:", error); - // return false; - // } - // } - - // // Now use the cached existingRecordRef - // const existingRecord = existingRecordRef.current; - - // try { - // const db = await getDBInstance(); // Reuse existing connection - // const tx = db.transaction("ChordsRecordings", "readwrite"); - // const store = tx.objectStore("ChordsRecordings"); - - // if (existingRecord) { - // // If the record exists, append data to it - // existingRecord.content.push(...data); - // await new Promise((resolve, reject) => { - // const putRequest = store.put(existingRecord); - // putRequest.onsuccess = () => resolve(); - // putRequest.onerror = () => reject(putRequest.error); - // }); - - // // Data appended to existing record - // } else { - // // If no record exists, create a new record and save data - // const newRecord = { - // filename: currentFilenameRef.current!, - // content: [...data], - // }; - - // await new Promise((resolve, reject) => { - // const putRequest = store.put(newRecord); - // putRequest.onsuccess = () => resolve(); - // putRequest.onerror = () => reject(putRequest.error); - // }); - - // // New record created and data saved - // } - - // return true; - // } catch (error) { - // console.error("Error writing to IndexedDB:", error); - // return false; - // } - // }, - // [canvasCount] - // ); - // Function to handle the recording process const handleRecord = async () => { if (isRecordingRef.current) { @@ -810,7 +760,6 @@ const Connection: React.FC = ({ setRecordingElapsedTime(0); setrecData(false); - // Reset only after stopping // setRecordingStartTime(0); recordingStartTime.current = 0; existingRecordRef.current = undefined; @@ -826,9 +775,7 @@ const Connection: React.FC = ({ fetchData(); }; - // Function to format time from seconds into a "MM:SS" string format - const formatTime = (milliseconds: number): string => { const date = new Date(milliseconds); const hours = String(date.getUTCHours()).padStart(2, '0'); @@ -837,47 +784,6 @@ const Connection: React.FC = ({ return `${hours}:${minutes}:${seconds}`; }; - // Function to initialize the IndexedDB and return a promise with the database instance - // const openIndexedDB = async (): Promise => { - // return new Promise((resolve, reject) => { - // // Open a connection to the IndexedDB database - // const request = indexedDB.open("ChordsRecordings", 2); // Update version if schema changes - - // request.onupgradeneeded = (event) => { - // const db = (event.target as IDBOpenDBRequest).result; - - // switch (event.oldVersion) { - // case 0: // Database doesn't exist, create initial schema - // const store = db.createObjectStore("ChordsRecordings", { - // keyPath: "filename", - // }); - // store.createIndex("filename", "filename", { unique: true }); - // break; - - // case 1: // Upgrade from version 1 to 2 - // const transaction = request.transaction; - // if (transaction) { - // const existingStore = transaction.objectStore("ChordsRecordings"); - // existingStore.createIndex("filename", "filename", { unique: true }); - // } - // break; - - // default: - // console.warn("No schema updates for this version."); - // } - // }; - - // request.onsuccess = (event) => { - // const db = (event.target as IDBOpenDBRequest).result; - // resolve(db); // Resolve the promise with the database instance - // }; - - // request.onerror = () => { - // reject(request.error); // Reject the promise with the error - // }; - // }); - // }; - // Function to delete files by filename const deleteFilesByFilename = async (filename: string) => { try { @@ -995,6 +901,7 @@ const Connection: React.FC = ({ toast.error("An unexpected error occurred. Please try again."); } }; + const openIndexedNDB = async (): Promise => { return new Promise((resolve, reject) => { const request = indexedDB.open("ChordsRecordings", 2); @@ -1012,33 +919,6 @@ const Connection: React.FC = ({ }); }; - // Function to get all data from IndexedDB - const getAllDataFromIndexedDB = async (): Promise => { - try { - const db = await openIndexedNDB(); - const tx = db.transaction(["ChordsRecordings"], "readonly"); - const store = tx.objectStore("ChordsRecordings"); - const request = store.getAll(); - return new Promise((resolve, reject) => { - request.onsuccess = () => { - const data = request.result.map((item: any, index: number) => ({ - id: index + 1, - ...item, - })); - resolve(data); - }; - - request.onerror = (error) => { - console.error("Error retrieving data from IndexedDB:", error); - reject(error); - }; - }); - } catch (error) { - console.error("Error during IndexedDB operation:", error); - return []; - } - }; - // Function to delete all data from IndexedDB (for ZIP files or clear all) const deleteAllDataFromIndexedDB = async () => { @@ -1105,50 +985,6 @@ const Connection: React.FC = ({ }); }; - // Function to save all datasets in IndexedDB as a ZIP file - const saveAllDataAsZip = async () => { - try { - // Open IndexedDB - const db = await openIndexedNDB(); - const tx = db.transaction("ChordsRecordings", "readonly"); - const store = tx.objectStore("ChordsRecordings"); - - // Retrieve all records from IndexedDB - const allData: any[] = await new Promise((resolve, reject) => { - const request = store.getAll(); - request.onsuccess = () => resolve(request.result); - request.onerror = () => reject(request.error); - }); - - if (allData.length === 0) { - toast.error("No data available to download."); - return; - } - - const zip = new JSZip(); - - // Add each record as a CSV file in the ZIP - allData.forEach((record) => { - const csvData = convertToCSV(record.content, canvasCount); // Convert record content to CSV with dynamic channels - zip.file(record.filename, csvData); // Use the filename for the CSV file - }); - - // Generate the ZIP file - const content = await zip.generateAsync({ type: "blob" }); - - // Download the ZIP file with a default name - saveAs(content, `ChordsWeb.zip`); // FileSaver.js for downloading - toast.success("ZIP file downloaded successfully."); - } catch (error) { - console.error("Error creating ZIP file:", error); - toast.error("Failed to create ZIP file. Please try again."); - } - }; - - - - - return (
{/* Left-aligned section */} diff --git a/workers/indexedDBWorker.ts b/workers/indexedDBWorker.ts index 2cefca5..5242271 100644 --- a/workers/indexedDBWorker.ts +++ b/workers/indexedDBWorker.ts @@ -1,5 +1,9 @@ +import { toast } from "sonner"; +import JSZip from 'jszip'; +import { saveAs } from 'file-saver'; self.onmessage = async (event) => { - const { action, data, filename } = event.data; + const { action, data, filename, canvasCount } = event.data; + // Open IndexedDB const db = await openIndexedDB(); @@ -9,7 +13,23 @@ self.onmessage = async (event) => { const success = await writeToIndexedDB(db, data, filename); self.postMessage({ success }); break; - + case 'getAllData': + try { + const allData = await getAllDataFromIndexedDB(db); + self.postMessage({ allData }); + } catch (error) { + self.postMessage({ error: 'Failed to retrieve all data from IndexedDB' }); + } + break; + case 'saveAllDataAsZip': + try { + await saveAllDataAsZip(); + self.postMessage({ success: true }); + } catch (error) { + self.postMessage({ success: false, error: 'Failed to create ZIP file' }); + } + break; + default: self.postMessage({ error: 'Invalid action' }); } @@ -72,4 +92,87 @@ self.onmessage = async (event) => { getRequest.onerror = () => resolve(false); }); }; - \ No newline at end of file + + + // Function to get all data +const getAllDataFromIndexedDB = async (db: IDBDatabase): Promise => { + return new Promise((resolve, reject) => { + const tx = db.transaction(["ChordsRecordings"], "readonly"); + const store = tx.objectStore("ChordsRecordings"); + const request = store.getAll(); + + request.onsuccess = () => { + const data = request.result.map((item: any, index: number) => ({ + id: index + 1, + ...item, + })); + resolve(data); + }; + + request.onerror = (error) => { + console.error("Error retrieving data from IndexedDB:", error); + reject(error); + }; + }); +}; + +// Function to save all data as a ZIP file +const saveAllDataAsZip = async (): Promise => { + try { + // Open IndexedDB + const db = await openIndexedDB(); + const tx = db.transaction("ChordsRecordings", "readonly"); + const store = tx.objectStore("ChordsRecordings"); + + // Retrieve all records from IndexedDB + const allData: any[] = await new Promise((resolve, reject) => { + const request = store.getAll(); + request.onsuccess = () => resolve(request.result); + request.onerror = () => reject(request.error); + }); + + if (allData.length === 0) { + toast.error("No data available to download."); + return; + } + + const zip = new JSZip(); + + // Assuming `canvasCount` is defined and passed to this function + const canvasCount = 4; // Example value, modify as needed + + // Add each record as a CSV file in the ZIP + allData.forEach((record) => { + const csvData = convertToCSV(record.content, canvasCount); // Convert record content to CSV with dynamic channels + zip.file(record.filename, csvData); // Use the filename for the CSV file + }); + + // Generate the ZIP file + const content = await zip.generateAsync({ type: "blob" }); + + // Download the ZIP file with a default name + saveAs(content, `ChordsWeb.zip`); // FileSaver.js for downloading + toast.success("ZIP file downloaded successfully."); + } catch (error) { + console.error("Error creating ZIP file:", error); + toast.error("Failed to create ZIP file. Please try again."); + } +}; + +// Function to convert data to CSV +const convertToCSV = (data: any[], canvasCount: number): string => { + if (data.length === 0) return ""; + + // Generate the header dynamically based on the number of channels + const header = ["Counter", ...Array.from({ length: canvasCount }, (_, i) => `Channel${i + 1}`)]; + + // Create rows by mapping data to match the header fields + const rows = data.map((item, index) => + [...item.slice(0, canvasCount + 1)].map((field) => + field !== undefined && field !== null ? JSON.stringify(field) : "" + ).join(",") + ); + + // Combine header and rows into a CSV format + return [header.join(","), ...rows].join("\n"); +}; \ No newline at end of file From a28e5b5fb77415ba1ed70342910abb9c840bfa05 Mon Sep 17 00:00:00 2001 From: Ritika Mishra Date: Sun, 15 Dec 2024 01:48:44 +0530 Subject: [PATCH 04/11] implemented web worker for save function --- src/components/Connection.tsx | 54 +++++++----------------- workers/indexedDBWorker.ts | 78 +++++++++++++++++------------------ 2 files changed, 51 insertions(+), 81 deletions(-) diff --git a/src/components/Connection.tsx b/src/components/Connection.tsx index 53573f5..77c1382 100644 --- a/src/components/Connection.tsx +++ b/src/components/Connection.tsx @@ -279,33 +279,24 @@ const Connection: React.FC = ({ const saveAllDataAsZip = async () => { try { - if (!workerRef.current) { - initializeWorker(); // Ensure the worker is initialized - } - - const canvasCount = 4; // Example value, modify as needed - workerRef.current?.postMessage({ action: 'saveAllDataAsZip', canvasCount }); + // Send message to worker to create ZIP file + if (workerRef.current) { + workerRef.current.postMessage({ action: 'saveAsZip' }); - return new Promise((resolve, reject) => { // Explicitly specify 'void' - if (workerRef.current) { - workerRef.current.onmessage = (event) => { - if (event.data.success) { - resolve(); // Resolving with no value - } else if (event.data.error) { - reject(event.data.error); - } - }; + // Listen for the response from the worker + workerRef.current.onmessage = async (event) => { + const { zipBlob, error } = event.data; - workerRef.current.onerror = (error) => { - reject(`Error in worker: ${error.message}`); + if (zipBlob) { + // Save the Blob as a ZIP file + saveAs(zipBlob, 'ChordsWeb.zip'); + } else if (error) { + console.error(error); }; - } else { - reject("Worker is not initialized"); - } - }); + }; + } } catch (error) { - console.error("Error in saveAllDataAsZip function:", error); - throw error; + console.error('Error while saving ZIP file:', error); } }; @@ -902,23 +893,6 @@ const Connection: React.FC = ({ } }; - const openIndexedNDB = async (): Promise => { - return new Promise((resolve, reject) => { - const request = indexedDB.open("ChordsRecordings", 2); - - request.onupgradeneeded = (event) => { - const db = (event.target as IDBOpenDBRequest).result; - const store = db.createObjectStore("ChordsRecordings", { - keyPath: "filename", - }); - store.createIndex("filename", "filename", { unique: true }); - }; - - request.onsuccess = (event) => resolve((event.target as IDBOpenDBRequest).result); - request.onerror = (event) => reject((event.target as IDBOpenDBRequest).error); - }); - }; - // Function to delete all data from IndexedDB (for ZIP files or clear all) const deleteAllDataFromIndexedDB = async () => { diff --git a/workers/indexedDBWorker.ts b/workers/indexedDBWorker.ts index 5242271..a2a3784 100644 --- a/workers/indexedDBWorker.ts +++ b/workers/indexedDBWorker.ts @@ -21,12 +21,12 @@ self.onmessage = async (event) => { self.postMessage({ error: 'Failed to retrieve all data from IndexedDB' }); } break; - case 'saveAllDataAsZip': + case 'saveAsZip': try { - await saveAllDataAsZip(); - self.postMessage({ success: true }); + const zipBlob = await saveAllDataAsZip(); + self.postMessage({ zipBlob }); } catch (error) { - self.postMessage({ success: false, error: 'Failed to create ZIP file' }); + self.postMessage({ error: 'Failed to create ZIP file' }); } break; @@ -116,63 +116,59 @@ const getAllDataFromIndexedDB = async (db: IDBDatabase): Promise => { }); }; + +// Function to convert data to CSV +// Function to convert data to CSV +const convertToCSV = (data: any[], canvasCount: number): string => { + if (!data || data.length === 0) return ""; + + // Generate the header dynamically based on the number of channels + const header = ["Counter", ...Array.from({ length: canvasCount }, (_, i) => `Channel${i + 1}`)]; + + // Create rows by mapping data to match the header fields + const rows = data.map((item, index) => + (item ? [...item.slice(0, canvasCount + 1)].map((field) => + field !== undefined && field !== null ? JSON.stringify(field) : "" + ).join(",") : "").trim() + ); + + // Combine header and rows into a CSV format + return [header.join(","), ...rows].join("\n"); +}; + // Function to save all data as a ZIP file -const saveAllDataAsZip = async (): Promise => { +const saveAllDataAsZip = async (): Promise => { try { - // Open IndexedDB const db = await openIndexedDB(); const tx = db.transaction("ChordsRecordings", "readonly"); const store = tx.objectStore("ChordsRecordings"); - // Retrieve all records from IndexedDB const allData: any[] = await new Promise((resolve, reject) => { const request = store.getAll(); request.onsuccess = () => resolve(request.result); request.onerror = () => reject(request.error); }); - if (allData.length === 0) { - toast.error("No data available to download."); - return; + if (!allData || allData.length === 0) { + throw new Error("No data available to download."); } const zip = new JSZip(); + const canvasCount = 4; // Assuming canvasCount is defined - // Assuming `canvasCount` is defined and passed to this function - const canvasCount = 4; // Example value, modify as needed - - // Add each record as a CSV file in the ZIP allData.forEach((record) => { - const csvData = convertToCSV(record.content, canvasCount); // Convert record content to CSV with dynamic channels - zip.file(record.filename, csvData); // Use the filename for the CSV file + try { + const csvData = convertToCSV(record.content, canvasCount); + zip.file(record.filename, csvData); + } catch (error) { + console.error(`Error processing record ${record.filename}:`, error); + } }); - // Generate the ZIP file const content = await zip.generateAsync({ type: "blob" }); - - // Download the ZIP file with a default name - saveAs(content, `ChordsWeb.zip`); // FileSaver.js for downloading - toast.success("ZIP file downloaded successfully."); + return content; } catch (error) { - console.error("Error creating ZIP file:", error); - toast.error("Failed to create ZIP file. Please try again."); + console.error("Error creating ZIP file in worker:", error); + throw error; } }; - -// Function to convert data to CSV -const convertToCSV = (data: any[], canvasCount: number): string => { - if (data.length === 0) return ""; - - // Generate the header dynamically based on the number of channels - const header = ["Counter", ...Array.from({ length: canvasCount }, (_, i) => `Channel${i + 1}`)]; - - // Create rows by mapping data to match the header fields - const rows = data.map((item, index) => - [...item.slice(0, canvasCount + 1)].map((field) => - field !== undefined && field !== null ? JSON.stringify(field) : "" - ).join(",") - ); - - // Combine header and rows into a CSV format - return [header.join(","), ...rows].join("\n"); -}; \ No newline at end of file From 239d6fc680d58f8f3fe462bd1834ceeb4f1b786c Mon Sep 17 00:00:00 2001 From: Ritika Mishra Date: Mon, 16 Dec 2024 18:47:58 +0530 Subject: [PATCH 05/11] added save functions in worker file --- src/components/Connection.tsx | 132 ++++++------------- workers/indexedDBWorker.ts | 239 ++++++++++++++++++++-------------- 2 files changed, 179 insertions(+), 192 deletions(-) diff --git a/src/components/Connection.tsx b/src/components/Connection.tsx index 77c1382..2d58b5b 100644 --- a/src/components/Connection.tsx +++ b/src/components/Connection.tsx @@ -242,24 +242,24 @@ const Connection: React.FC = ({ if (filename) { // Check if the record already exists - workerRef.current?.postMessage({ action: 'checkExistence', filename }); + workerRef.current?.postMessage({ action: 'checkExistence', filename, canvasCount }); writeToIndexedDB(data, filename); } }; const writeToIndexedDB = (data: number[][], filename: string) => { - workerRef.current?.postMessage({ action: 'write', data, filename }); + workerRef.current?.postMessage({ action: 'write', data, filename, canvasCount }); }; const getAllDataFromIndexedDB = async (): Promise => { if (!workerRef.current) { initializeWorker(); } - + return new Promise((resolve, reject) => { if (workerRef.current) { workerRef.current.postMessage({ action: 'getAllData' }); - + workerRef.current.onmessage = (event) => { if (event.data.allData) { resolve(event.data.allData); @@ -267,7 +267,7 @@ const Connection: React.FC = ({ reject(event.data.error); } }; - + workerRef.current.onerror = (error) => { reject(`Error in worker: ${error.message}`); }; @@ -276,30 +276,52 @@ const Connection: React.FC = ({ } }); }; - + const saveAllDataAsZip = async () => { try { - // Send message to worker to create ZIP file if (workerRef.current) { - workerRef.current.postMessage({ action: 'saveAsZip' }); - - // Listen for the response from the worker + workerRef.current.postMessage({ action: 'saveAsZip', canvasCount }); + workerRef.current.onmessage = async (event) => { const { zipBlob, error } = event.data; - + if (zipBlob) { - // Save the Blob as a ZIP file saveAs(zipBlob, 'ChordsWeb.zip'); } else if (error) { console.error(error); - }; + } }; } } catch (error) { console.error('Error while saving ZIP file:', error); } }; - + + + // Function to handle saving data by filename + const saveDataByFilename = async (filename: string, canvasCount: number) => { + if (workerRef.current) { + workerRef.current.postMessage({ action: 'saveDataByFilename', filename, canvasCount }); + + workerRef.current.onmessage = (event) => { + const { blob, error } = event.data; + + if (blob) { + saveAs(blob, filename); // FileSaver.js + toast.success("File downloaded successfully."); + } + }; + + workerRef.current.onerror = (error) => { + console.error("Worker error:", error); + toast.error("An unexpected worker error occurred."); + }; + } else { + console.error("Worker reference is null."); + toast.error("Worker is not available."); + } + }; + ////////////////////////////////////////// const handleCustomTimeChange = (e: React.ChangeEvent) => { @@ -700,23 +722,6 @@ const Connection: React.FC = ({ } }; - const convertToCSV = (data: any[], canvasCount: number): string => { - if (data.length === 0) return ""; - - // Generate the header dynamically based on the number of channels - const header = ["Counter", ...Array.from({ length: canvasCount }, (_, i) => `Channel${i + 1}`)]; - - // Create rows by mapping data to match the header fields - const rows = data.map((item, index) => - [...item.slice(0, canvasCount + 1)].map((field) => - field !== undefined && field !== null ? JSON.stringify(field) : "" - ).join(",") - ); - - // Combine header and rows into a CSV format - return [header.join(","), ...rows].join("\n"); - }; - const existingRecordRef = useRef(undefined); // Function to handle the recording process const handleRecord = async () => { @@ -744,24 +749,19 @@ const Connection: React.FC = ({ toast.error("Recording start time was not captured."); return; } - const endTime = new Date(); const durationInSeconds = Math.floor((Date.now() - recordingStartTime.current) / 1000); isRecordingRef.current = false; setRecordingElapsedTime(0); setrecData(false); - // setRecordingStartTime(0); recordingStartTime.current = 0; existingRecordRef.current = undefined; - - // Re-fetch datasets from IndexedDB after recording stops const fetchData = async () => { const data = await getAllDataFromIndexedDB(); setDatasets(data); // Update datasets with the latest data }; - // Call fetchData after stopping the recording fetchData(); }; @@ -834,65 +834,7 @@ const Connection: React.FC = ({ } }; - const saveDataByFilename = async (filename: string) => { - try { - // Open the IndexedDB connection - const dbRequest = indexedDB.open("ChordsRecordings"); - - dbRequest.onsuccess = (event) => { - const db = (event.target as IDBOpenDBRequest).result; - const transaction = db.transaction("ChordsRecordings", "readonly"); - const store = transaction.objectStore("ChordsRecordings"); - - // Check if the "filename" index exists - if (!store.indexNames.contains("filename")) { - console.error("Index 'filename' does not exist."); - toast.error("Unable to download files: index not found."); - return; - } - - // Retrieve the data by filename - const index = store.index("filename"); - const getRequest = index.get(filename); - - getRequest.onsuccess = (event) => { - const result = getRequest.result; - - // Ensure the file exists and contains data - if (!result || !Array.isArray(result.content)) { - toast.error("No data found for the given filename."); - return; - } - - // Convert data to CSV, passing canvasCount dynamically - const csvData = convertToCSV(result.content, canvasCount); - - // Create a Blob from the CSV data - const blob = new Blob([csvData], { type: "text/csv;charset=utf-8" }); - // Trigger the download with the filename - saveAs(blob, filename); // FileSaver.js - - // Show a success message - toast.success("File downloaded successfully."); - }; - - getRequest.onerror = () => { - console.error("Error during file retrieval."); - toast.error("Failed to retrieve the file. Please try again."); - }; - }; - - dbRequest.onerror = () => { - console.error("Failed to open IndexedDB database."); - toast.error("An error occurred while accessing the database."); - }; - } catch (error) { - console.error("Error occurred during file download:", error); - toast.error("An unexpected error occurred. Please try again."); - } - }; - // Function to delete all data from IndexedDB (for ZIP files or clear all) const deleteAllDataFromIndexedDB = async () => { @@ -1213,7 +1155,7 @@ const Connection: React.FC = ({
{/* Save file by filename */} +
)) diff --git a/workers/indexedDBWorker.ts b/workers/indexedDBWorker.ts index b1d0429..3a2a601 100644 --- a/workers/indexedDBWorker.ts +++ b/workers/indexedDBWorker.ts @@ -1,6 +1,5 @@ -import { toast } from "sonner"; + import JSZip from 'jszip'; -import { saveAs } from 'file-saver'; self.onmessage = async (event) => { const { action, data, filename, canvasCount } = event.data; @@ -21,6 +20,14 @@ self.onmessage = async (event) => { self.postMessage({ error: 'Failed to retrieve all data from IndexedDB' }); } break; + case 'getFileCountFromIndexedDB': + try { + const allData = await getFileCountFromIndexedDB(db); + self.postMessage({ allData }); + } catch (error) { + self.postMessage({ error: 'Failed to retrieve all data from IndexedDB' }); + } + break; case 'saveAsZip': try { const zipBlob = await saveAllDataAsZip(canvasCount); @@ -113,25 +120,37 @@ const getAllDataFromIndexedDB = async (db: IDBDatabase): Promise => { }; + + + // Function to convert data to CSV const convertToCSV = (data: any[], canvasCount: number): string => { - if (data.length === 0) return ""; + if (!Array.isArray(data) || data.length === 0) return ""; // Generate the header dynamically based on the number of channels const header = ["Counter", ...Array.from({ length: canvasCount }, (_, i) => `Channel${i + 1}`)]; - // Create rows by mapping data to match the header fields - const rows = data.map((item, index) => - [...item.slice(0, canvasCount + 1)].map((field) => - field !== undefined && field !== null ? JSON.stringify(field) : "" - ).join(",") - ); + // Create rows by filtering and mapping valid data + const rows = data + .filter((item, index) => { + if (!item || !Array.isArray(item)) { + console.warn(`Skipping invalid data at index ${index}:`, item); + return false; + } + return true; + }) + .map((item) => + [...item.slice(0, canvasCount + 1)] + .map((field) => (field !== undefined && field !== null ? JSON.stringify(field) : "")) + .join(",") + ); // Combine header and rows into a CSV format return [header.join(","), ...rows].join("\n"); }; + // Function to save all data as a ZIP file const saveAllDataAsZip = async (canvasCount: number): Promise => { try { @@ -171,6 +190,7 @@ const saveAllDataAsZip = async (canvasCount: number): Promise => { const saveDataByFilename = async (filename: string, canvasCount: number): Promise => { try { + console.log("filename",filename); const dbRequest = indexedDB.open("ChordsRecordings"); return new Promise((resolve, reject) => { @@ -179,7 +199,6 @@ const saveDataByFilename = async (filename: string, canvasCount: number): Promis const transaction = db.transaction("ChordsRecordings", "readonly"); const store = transaction.objectStore("ChordsRecordings"); - // Ensure the "filename" index exists if (!store.indexNames.contains("filename")) { reject(new Error("Index 'filename' does not exist.")); return; @@ -190,9 +209,16 @@ const saveDataByFilename = async (filename: string, canvasCount: number): Promis getRequest.onsuccess = () => { const result = getRequest.result; + console.log("Retrieved IndexedDB result:", result); if (!result || !Array.isArray(result.content)) { - reject(new Error("No data found for the given filename.")); + reject(new Error("No data found for the given filename or invalid data format.")); + return; + } + + // Validate `result.content` before processing + if (!result.content.every((item: any) => Array.isArray(item))) { + reject(new Error("Content data contains invalid or non-array elements.")); return; } @@ -215,5 +241,32 @@ const saveDataByFilename = async (filename: string, canvasCount: number): Promis } }; +const getFileCountFromIndexedDB = async (db: IDBDatabase): Promise => { + return new Promise((resolve, reject) => { + const tx = db.transaction(["ChordsRecordings"], "readonly"); + const store = tx.objectStore("ChordsRecordings"); + const filenames: string[] = []; + + const cursorRequest = store.openCursor(); + cursorRequest.onsuccess = (event) => { + const cursor = (event.target as IDBRequest).result as IDBCursorWithValue | null; + if (cursor) { + const record = cursor.value; + if (record.filename) { + filenames.push(record.filename); // Replace `filename` with your actual property name + } + cursor.continue(); + } else { + resolve(filenames); // All filenames collected + } + }; + + cursorRequest.onerror = (event) => { + const error = (event.target as IDBRequest).error; + console.error("Error retrieving filenames from IndexedDB:", error); + reject(error); + }; + }); +}; From 03b1b5c255f2391034c6c331c1f90119a311a418 Mon Sep 17 00:00:00 2001 From: Ritika Mishra Date: Wed, 18 Dec 2024 13:31:47 +0530 Subject: [PATCH 07/11] improved code to update canvas count --- src/components/Connection.tsx | 43 +++++------------------------------ workers/indexedDBWorker.ts | 4 ++-- 2 files changed, 8 insertions(+), 39 deletions(-) diff --git a/src/components/Connection.tsx b/src/components/Connection.tsx index fa15b8a..15f44b1 100644 --- a/src/components/Connection.tsx +++ b/src/components/Connection.tsx @@ -157,8 +157,6 @@ const Connection: React.FC = ({ } }; - - const decreaseCanvas = () => { if (canvasCount > 1) { setCanvasCount(canvasCount - 1); // Decrease canvas count but not below 1 @@ -198,7 +196,7 @@ const Connection: React.FC = ({ useEffect(() => { canvasnumbersRef.current = canvasCount; // Sync the ref with the state - }, [canvasCount]); + }, [canvasCount,isRecordingRef]); const handleTimeSelection = (minutes: number | null) => { // Function to handle the time selection @@ -229,7 +227,7 @@ const Connection: React.FC = ({ } }; - const processBuffer = async (bufferIndex: number) => { + const processBuffer = async (bufferIndex: number,canvasCount:number) => { if (!workerRef.current) { initializeWorker(); } @@ -243,40 +241,14 @@ const Connection: React.FC = ({ if (filename) { // Check if the record already exists workerRef.current?.postMessage({ action: 'checkExistence', filename, canvasCount }); - writeToIndexedDB(data, filename); + writeToIndexedDB(data, filename,canvasCount); } }; - const writeToIndexedDB = (data: number[][], filename: string) => { + const writeToIndexedDB = (data: number[][], filename: string,canvasCount:number) => { workerRef.current?.postMessage({ action: 'write', data, filename, canvasCount }); }; - const getAllDataFromIndexedDB = async (): Promise => { - if (!workerRef.current) { - initializeWorker(); - } - - return new Promise((resolve, reject) => { - if (workerRef.current) { - workerRef.current.postMessage({ action: 'getAllData' }); - - workerRef.current.onmessage = (event) => { - if (event.data.allData) { - resolve(event.data.allData); - } else if (event.data.error) { - reject(event.data.error); - } - }; - - workerRef.current.onerror = (error) => { - reject(`Error in worker: ${error.message}`); - }; - } else { - reject('Worker is not initialized'); - } - }); - }; - const saveAllDataAsZip = async () => { try { if (workerRef.current) { @@ -487,7 +459,6 @@ const Connection: React.FC = ({ }; - const getFileCountFromIndexedDB = async (): Promise => { if (!workerRef.current) { initializeWorker(); @@ -701,6 +672,7 @@ const Connection: React.FC = ({ } datastream(channelData); // Pass the channel data to the LineData function for further processing if (isRecordingRef.current) { + console.log(canvasnumbersRef.current); const channeldatavalues = channelData .slice(0, canvasnumbersRef.current + 1) .map((value) => (value !== undefined ? value : null)) @@ -710,7 +682,7 @@ const Connection: React.FC = ({ // activeBuffer.push(channeldatavalues); // Store the channel data in the recording buffer if (fillingindex.current >= MAX_BUFFER_SIZE - 1) { - processBuffer(activeBufferIndex); + processBuffer(activeBufferIndex,canvasnumbersRef.current); activeBufferIndex = (activeBufferIndex + 1) % NUM_BUFFERS; } fillingindex.current = (fillingindex.current + 1) % MAX_BUFFER_SIZE; @@ -792,8 +764,6 @@ const Connection: React.FC = ({ const data = await getFileCountFromIndexedDB(); setDatasets(data); // Update datasets with the latest data }; - - // Call fetchData after stopping the recording fetchData(); }; @@ -866,7 +836,6 @@ const Connection: React.FC = ({ } }; - // Function to delete all data from IndexedDB (for ZIP files or clear all) const deleteAllDataFromIndexedDB = async () => { return new Promise((resolve, reject) => { diff --git a/workers/indexedDBWorker.ts b/workers/indexedDBWorker.ts index 3a2a601..14d6631 100644 --- a/workers/indexedDBWorker.ts +++ b/workers/indexedDBWorker.ts @@ -9,7 +9,7 @@ self.onmessage = async (event) => { switch (action) { case 'write': - const success = await writeToIndexedDB(db, data, filename); + const success = await writeToIndexedDB(db, data, filename,canvasCount); self.postMessage({ success }); break; case 'getAllData': @@ -70,7 +70,7 @@ const openIndexedDB = async (): Promise => { }; // Function to write data to IndexedDB -const writeToIndexedDB = async (db: IDBDatabase, data: number[][], filename: string): Promise => { +const writeToIndexedDB = async (db: IDBDatabase, data: number[][], filename: string,canvasCount:number): Promise => { return new Promise((resolve, reject) => { const tx = db.transaction("ChordsRecordings", "readwrite"); const store = tx.objectStore("ChordsRecordings"); From fbb5a947d37cfa503693a447981e4c139211b26f Mon Sep 17 00:00:00 2001 From: Ritika Mishra Date: Thu, 19 Dec 2024 11:54:59 +0530 Subject: [PATCH 08/11] format code removed unwanted variables and extra spaces --- src/components/Connection.tsx | 33 +++++++++------------------------ workers/indexedDBWorker.ts | 10 ---------- 2 files changed, 9 insertions(+), 34 deletions(-) diff --git a/src/components/Connection.tsx b/src/components/Connection.tsx index 15f44b1..f631f6b 100644 --- a/src/components/Connection.tsx +++ b/src/components/Connection.tsx @@ -3,7 +3,6 @@ import React, { useState, useRef, useCallback, useEffect } from "react"; import { Button } from "./ui/button"; import { Input } from "./ui/input"; import { EXGFilter, Notch } from './filters'; -import JSZip from 'jszip'; import { Cable, Circle, @@ -67,7 +66,6 @@ const Connection: React.FC = ({ onPauseChange, datastream, Connection, - selectedBits, setSelectedBits, isDisplay, setIsDisplay, @@ -85,20 +83,17 @@ const Connection: React.FC = ({ const [isEndTimePopoverOpen, setIsEndTimePopoverOpen] = useState(false); const [detectedBits, setDetectedBits] = useState(null); // State to store the detected bits const detectedBitsRef = React.useRef("ten"); - const [isRecordButtonDisabled, setIsRecordButtonDisabled] = useState(false); // New state variable const [datasets, setDatasets] = useState([]); const currentFilenameRef = useRef(""); - const [hasData, setHasData] = useState(false); - const [recData, setrecData] = useState(false); + const [isRecordButtonDisabled, setIsRecordButtonDisabled] = useState(false); const [recordingElapsedTime, setRecordingElapsedTime] = useState(0); // State to store the recording duration - const [elapsedTime, setElapsedTime] = useState(0); // State to store the recording duration const recordingStartTime = useRef(0); const [customTime, setCustomTime] = useState(""); // State to store the custom stop time input + const [clickCount, setClickCount] = useState(0); // Track how many times the left arrow is clicked const endTimeRef = useRef(null); // Ref to store the end time of the recording const [popoverVisible, setPopoverVisible] = useState(false); const portRef = useRef(null); // Ref to store the serial port - const indexedDBRef = useRef(null); - const [ifBits, setifBits] = useState("auto"); + const [ifBits, setifBits] = useState("auto"); const [showAllChannels, setShowAllChannels] = useState(false); const [FullZoom, setFullZoom] = useState(false); const canvasnumbersRef = useRef(1); @@ -132,8 +127,6 @@ const Connection: React.FC = ({ } }; - const [clickCount, setClickCount] = useState(0); // Track how many times the left arrow is clicked - const enabledClicks = (snapShotRef.current?.filter(Boolean).length ?? 0) - 1; // Enable/Disable left arrow button @@ -193,7 +186,6 @@ const Connection: React.FC = ({ } }; - useEffect(() => { canvasnumbersRef.current = canvasCount; // Sync the ref with the state }, [canvasCount,isRecordingRef]); @@ -269,7 +261,6 @@ const Connection: React.FC = ({ } }; - // Function to handle saving data by filename const saveDataByFilename = async (filename: string, canvasCount: number) => { if (workerRef.current) { @@ -354,7 +345,6 @@ const Connection: React.FC = ({ baudRate: number; } - const connectToDevice = async () => { try { if (portRef.current && portRef.current.readable) { @@ -485,7 +475,6 @@ const Connection: React.FC = ({ }); }; - const disconnectDevice = async (): Promise => { try { if (portRef.current) { @@ -679,8 +668,7 @@ const Connection: React.FC = ({ .filter((value): value is number => value !== null); // Filter out null values // Check if recording is enabled recordingBuffers[activeBufferIndex][fillingindex.current] = channeldatavalues; - // activeBuffer.push(channeldatavalues); // Store the channel data in the recording buffer - + if (fillingindex.current >= MAX_BUFFER_SIZE - 1) { processBuffer(activeBufferIndex,canvasnumbersRef.current); activeBufferIndex = (activeBufferIndex + 1) % NUM_BUFFERS; @@ -736,8 +724,7 @@ const Connection: React.FC = ({ const now = new Date(); recordingStartTime.current = Date.now(); setRecordingElapsedTime(Date.now()); - setrecData(true); - + setIsRecordButtonDisabled(true); const filename = `ChordsWeb-${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}-` + `${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}.csv`; @@ -751,11 +738,9 @@ const Connection: React.FC = ({ toast.error("Recording start time was not captured."); return; } - const endTime = new Date(); - const durationInSeconds = Math.floor((Date.now() - recordingStartTime.current) / 1000); isRecordingRef.current = false; setRecordingElapsedTime(0); - setrecData(false); + setIsRecordButtonDisabled(false); // setRecordingStartTime(0); recordingStartTime.current = 0; existingRecordRef.current = undefined; @@ -1452,7 +1437,7 @@ const Connection: React.FC = ({ @@ -1474,7 +1459,7 @@ const Connection: React.FC = ({ @@ -1496,7 +1481,7 @@ const Connection: React.FC = ({ diff --git a/workers/indexedDBWorker.ts b/workers/indexedDBWorker.ts index 14d6631..11c26a9 100644 --- a/workers/indexedDBWorker.ts +++ b/workers/indexedDBWorker.ts @@ -3,7 +3,6 @@ import JSZip from 'jszip'; self.onmessage = async (event) => { const { action, data, filename, canvasCount } = event.data; - // Open IndexedDB const db = await openIndexedDB(); @@ -44,8 +43,6 @@ self.onmessage = async (event) => { self.postMessage({ error }); } break; - - default: self.postMessage({ error: 'Invalid action' }); } @@ -92,7 +89,6 @@ const writeToIndexedDB = async (db: IDBDatabase, data: number[][], filename: str putRequest.onerror = () => reject(false); } }; - getRequest.onerror = () => reject(false); }); }; @@ -119,10 +115,6 @@ const getAllDataFromIndexedDB = async (db: IDBDatabase): Promise => { }); }; - - - - // Function to convert data to CSV const convertToCSV = (data: any[], canvasCount: number): string => { if (!Array.isArray(data) || data.length === 0) return ""; @@ -149,8 +141,6 @@ const convertToCSV = (data: any[], canvasCount: number): string => { return [header.join(","), ...rows].join("\n"); }; - - // Function to save all data as a ZIP file const saveAllDataAsZip = async (canvasCount: number): Promise => { try { From 00a961114ab7f2abb57c3cc47fbfc4bbe8b2a273 Mon Sep 17 00:00:00 2001 From: Ritika Mishra Date: Thu, 19 Dec 2024 13:05:39 +0530 Subject: [PATCH 09/11] format code removed unwanted console checks --- src/components/Connection.tsx | 37 +++++++++++++++++------------------ workers/indexedDBWorker.ts | 7 ++----- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/components/Connection.tsx b/src/components/Connection.tsx index f631f6b..e2209fb 100644 --- a/src/components/Connection.tsx +++ b/src/components/Connection.tsx @@ -93,7 +93,7 @@ const Connection: React.FC = ({ const endTimeRef = useRef(null); // Ref to store the end time of the recording const [popoverVisible, setPopoverVisible] = useState(false); const portRef = useRef(null); // Ref to store the serial port - const [ifBits, setifBits] = useState("auto"); + const [ifBits, setifBits] = useState("auto"); const [showAllChannels, setShowAllChannels] = useState(false); const [FullZoom, setFullZoom] = useState(false); const canvasnumbersRef = useRef(1); @@ -188,7 +188,7 @@ const Connection: React.FC = ({ useEffect(() => { canvasnumbersRef.current = canvasCount; // Sync the ref with the state - }, [canvasCount,isRecordingRef]); + }, [canvasCount, isRecordingRef]); const handleTimeSelection = (minutes: number | null) => { // Function to handle the time selection @@ -219,7 +219,7 @@ const Connection: React.FC = ({ } }; - const processBuffer = async (bufferIndex: number,canvasCount:number) => { + const processBuffer = async (bufferIndex: number, canvasCount: number) => { if (!workerRef.current) { initializeWorker(); } @@ -233,11 +233,11 @@ const Connection: React.FC = ({ if (filename) { // Check if the record already exists workerRef.current?.postMessage({ action: 'checkExistence', filename, canvasCount }); - writeToIndexedDB(data, filename,canvasCount); + writeToIndexedDB(data, filename, canvasCount); } }; - const writeToIndexedDB = (data: number[][], filename: string,canvasCount:number) => { + const writeToIndexedDB = (data: number[][], filename: string, canvasCount: number) => { workerRef.current?.postMessage({ action: 'write', data, filename, canvasCount }); }; @@ -271,7 +271,7 @@ const Connection: React.FC = ({ if (blob) { saveAs(blob, filename); // FileSaver.js toast.success("File downloaded successfully."); - } else(error:any) =>{ + } else (error: any) => { console.error("Worker error:", error); toast.error(`Error during file download: ${error.message}`); } @@ -661,16 +661,15 @@ const Connection: React.FC = ({ } datastream(channelData); // Pass the channel data to the LineData function for further processing if (isRecordingRef.current) { - console.log(canvasnumbersRef.current); const channeldatavalues = channelData .slice(0, canvasnumbersRef.current + 1) .map((value) => (value !== undefined ? value : null)) .filter((value): value is number => value !== null); // Filter out null values // Check if recording is enabled recordingBuffers[activeBufferIndex][fillingindex.current] = channeldatavalues; - + if (fillingindex.current >= MAX_BUFFER_SIZE - 1) { - processBuffer(activeBufferIndex,canvasnumbersRef.current); + processBuffer(activeBufferIndex, canvasnumbersRef.current); activeBufferIndex = (activeBufferIndex + 1) % NUM_BUFFERS; } fillingindex.current = (fillingindex.current + 1) % MAX_BUFFER_SIZE; @@ -765,26 +764,26 @@ const Connection: React.FC = ({ const deleteFilesByFilename = async (filename: string) => { try { const dbRequest = indexedDB.open("ChordsRecordings"); - + dbRequest.onsuccess = (event) => { const db = (event.target as IDBOpenDBRequest).result; const transaction = db.transaction("ChordsRecordings", "readwrite"); const store = transaction.objectStore("ChordsRecordings"); - + // Check if the "filename" index exists if (!store.indexNames.contains("filename")) { console.error("Index 'filename' does not exist."); toast.error("Unable to delete files: index not found."); return; } - + const index = store.index("filename"); const deleteRequest = index.openCursor(IDBKeyRange.only(filename)); - + // Make this callback async deleteRequest.onsuccess = async (event) => { const cursor = (event.target as IDBRequest).result; - + if (cursor) { cursor.delete(); // Delete the current record // Fetch the updated data and update state @@ -795,22 +794,22 @@ const Connection: React.FC = ({ toast.success("File deleted successfully."); } }; - + deleteRequest.onerror = () => { console.error("Error during delete operation."); toast.error("Failed to delete the file. Please try again."); }; - + transaction.oncomplete = () => { console.log("File deletion transaction completed."); }; - + transaction.onerror = () => { console.error("Transaction failed during deletion."); toast.error("Failed to delete the file. Please try again."); }; }; - + dbRequest.onerror = () => { console.error("Failed to open IndexedDB database."); toast.error("An error occurred while accessing the database."); @@ -820,7 +819,7 @@ const Connection: React.FC = ({ toast.error("An unexpected error occurred. Please try again."); } }; - + // Function to delete all data from IndexedDB (for ZIP files or clear all) const deleteAllDataFromIndexedDB = async () => { return new Promise((resolve, reject) => { diff --git a/workers/indexedDBWorker.ts b/workers/indexedDBWorker.ts index 11c26a9..490fe41 100644 --- a/workers/indexedDBWorker.ts +++ b/workers/indexedDBWorker.ts @@ -8,7 +8,7 @@ self.onmessage = async (event) => { switch (action) { case 'write': - const success = await writeToIndexedDB(db, data, filename,canvasCount); + const success = await writeToIndexedDB(db, data, filename, canvasCount); self.postMessage({ success }); break; case 'getAllData': @@ -67,7 +67,7 @@ const openIndexedDB = async (): Promise => { }; // Function to write data to IndexedDB -const writeToIndexedDB = async (db: IDBDatabase, data: number[][], filename: string,canvasCount:number): Promise => { +const writeToIndexedDB = async (db: IDBDatabase, data: number[][], filename: string, canvasCount: number): Promise => { return new Promise((resolve, reject) => { const tx = db.transaction("ChordsRecordings", "readwrite"); const store = tx.objectStore("ChordsRecordings"); @@ -148,7 +148,6 @@ const saveAllDataAsZip = async (canvasCount: number): Promise => { const tx = db.transaction("ChordsRecordings", "readonly"); const store = tx.objectStore("ChordsRecordings"); - console.log(canvasCount); const allData: any[] = await new Promise((resolve, reject) => { const request = store.getAll(); request.onsuccess = () => resolve(request.result); @@ -180,7 +179,6 @@ const saveAllDataAsZip = async (canvasCount: number): Promise => { const saveDataByFilename = async (filename: string, canvasCount: number): Promise => { try { - console.log("filename",filename); const dbRequest = indexedDB.open("ChordsRecordings"); return new Promise((resolve, reject) => { @@ -199,7 +197,6 @@ const saveDataByFilename = async (filename: string, canvasCount: number): Promis getRequest.onsuccess = () => { const result = getRequest.result; - console.log("Retrieved IndexedDB result:", result); if (!result || !Array.isArray(result.content)) { reject(new Error("No data found for the given filename or invalid data format.")); From 8bb3a92639167d11c12e84fef6a9b65a6e5f48c8 Mon Sep 17 00:00:00 2001 From: Ritika Mishra Date: Thu, 19 Dec 2024 23:28:34 +0530 Subject: [PATCH 10/11] updated version of chords and next.js --- package-lock.json | 107 +++++++++++++++++++++++++--------------------- package.json | 6 +-- tsconfig.json | 2 + 3 files changed, 64 insertions(+), 51 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7a4faa0..bfdd831 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { - "name": "Chords", - "version": "2.3.0a", + "name": "chords", + "version": "2.3.2a", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "Chords", - "version": "2.3.0a", + "name": "chords", + "version": "2.3.2a", "dependencies": { "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-avatar": "^1.0.4", @@ -36,7 +36,7 @@ "html2canvas": "^1.4.1", "jszip": "^3.10.1", "lucide-react": "^0.460.0", - "next": "14.2.15", + "next": "14.2.20", "next-themes": "^0.3.0", "react": "^18", "react-dom": "^18", @@ -436,9 +436,10 @@ } }, "node_modules/@next/env": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.15.tgz", - "integrity": "sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ==" + "version": "14.2.20", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.20.tgz", + "integrity": "sha512-JfDpuOCB0UBKlEgEy/H6qcBSzHimn/YWjUHzKl1jMeUO+QVRdzmTTl8gFJaNO87c8DXmVKhFCtwxQ9acqB3+Pw==", + "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { "version": "14.2.3", @@ -451,12 +452,13 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz", - "integrity": "sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==", + "version": "14.2.20", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.20.tgz", + "integrity": "sha512-WDfq7bmROa5cIlk6ZNonNdVhKmbCv38XteVFYsxea1vDJt3SnYGgxLGMTXQNfs5OkFvAhmfKKrwe7Y0Hs+rWOg==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -466,12 +468,13 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz", - "integrity": "sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==", + "version": "14.2.20", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.20.tgz", + "integrity": "sha512-XIQlC+NAmJPfa2hruLvr1H1QJJeqOTDV+v7tl/jIdoFvqhoihvSNykLU/G6NMgoeo+e/H7p/VeWSOvMUHKtTIg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -481,12 +484,13 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz", - "integrity": "sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==", + "version": "14.2.20", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.20.tgz", + "integrity": "sha512-pnzBrHTPXIMm5QX3QC8XeMkpVuoAYOmyfsO4VlPn+0NrHraNuWjdhe+3xLq01xR++iCvX+uoeZmJDKcOxI201Q==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -496,12 +500,13 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz", - "integrity": "sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==", + "version": "14.2.20", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.20.tgz", + "integrity": "sha512-WhJJAFpi6yqmUx1momewSdcm/iRXFQS0HU2qlUGlGE/+98eu7JWLD5AAaP/tkK1mudS/rH2f9E3WCEF2iYDydQ==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -511,12 +516,13 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz", - "integrity": "sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==", + "version": "14.2.20", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.20.tgz", + "integrity": "sha512-ao5HCbw9+iG1Kxm8XsGa3X174Ahn17mSYBQlY6VGsdsYDAbz/ZP13wSLfvlYoIDn1Ger6uYA+yt/3Y9KTIupRg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -526,12 +532,13 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz", - "integrity": "sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==", + "version": "14.2.20", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.20.tgz", + "integrity": "sha512-CXm/kpnltKTT7945np6Td3w7shj/92TMRPyI/VvveFe8+YE+/YOJ5hyAWK5rpx711XO1jBCgXl211TWaxOtkaA==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -541,12 +548,13 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz", - "integrity": "sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==", + "version": "14.2.20", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.20.tgz", + "integrity": "sha512-upJn2HGQgKNDbXVfIgmqT2BN8f3z/mX8ddoyi1I565FHbfowVK5pnMEwauvLvaJf4iijvuKq3kw/b6E9oIVRWA==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -556,12 +564,13 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz", - "integrity": "sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==", + "version": "14.2.20", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.20.tgz", + "integrity": "sha512-igQW/JWciTGJwj3G1ipalD2V20Xfx3ywQy17IV0ciOUBbFhNfyU1DILWsTi32c8KmqgIDviUEulW/yPb2FF90w==", "cpu": [ "ia32" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -571,12 +580,13 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.15.tgz", - "integrity": "sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g==", + "version": "14.2.20", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.20.tgz", + "integrity": "sha512-AFmqeLW6LtxeFTuoB+MXFeM5fm5052i3MU6xD0WzJDOwku6SkZaxb1bxjBaRC8uNqTRTSPl0yMFtjNowIVI67w==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -5391,11 +5401,12 @@ "license": "MIT" }, "node_modules/next": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.15.tgz", - "integrity": "sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==", + "version": "14.2.20", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.20.tgz", + "integrity": "sha512-yPvIiWsiyVYqJlSQxwmzMIReXn5HxFNq4+tlVQ812N1FbvhmE+fDpIAD7bcS2mGYQwPJ5vAsQouyme2eKsxaug==", + "license": "MIT", "dependencies": { - "@next/env": "14.2.15", + "@next/env": "14.2.20", "@swc/helpers": "0.5.5", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", @@ -5410,15 +5421,15 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.15", - "@next/swc-darwin-x64": "14.2.15", - "@next/swc-linux-arm64-gnu": "14.2.15", - "@next/swc-linux-arm64-musl": "14.2.15", - "@next/swc-linux-x64-gnu": "14.2.15", - "@next/swc-linux-x64-musl": "14.2.15", - "@next/swc-win32-arm64-msvc": "14.2.15", - "@next/swc-win32-ia32-msvc": "14.2.15", - "@next/swc-win32-x64-msvc": "14.2.15" + "@next/swc-darwin-arm64": "14.2.20", + "@next/swc-darwin-x64": "14.2.20", + "@next/swc-linux-arm64-gnu": "14.2.20", + "@next/swc-linux-arm64-musl": "14.2.20", + "@next/swc-linux-x64-gnu": "14.2.20", + "@next/swc-linux-x64-musl": "14.2.20", + "@next/swc-win32-arm64-msvc": "14.2.20", + "@next/swc-win32-ia32-msvc": "14.2.20", + "@next/swc-win32-x64-msvc": "14.2.20" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", diff --git a/package.json b/package.json index 44d791d..4518a82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "Chords", - "version": "2.3.0a", + "name": "chords", + "version": "2.3.2a", "private": true, "type": "module", "scripts": { @@ -40,7 +40,7 @@ "html2canvas": "^1.4.1", "jszip": "^3.10.1", "lucide-react": "^0.460.0", - "next": "14.2.15", + "next": "14.2.20", "next-themes": "^0.3.0", "react": "^18", "react-dom": "^18", diff --git a/tsconfig.json b/tsconfig.json index a7f1e75..c1f3247 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -32,6 +32,8 @@ "next-env.d.ts", "**/*.ts", ".next/types/**/*.ts", + "**/*.ts", + "**/*.tsx", "out/types/**/*.ts" ], "exclude": [ From 339629cf767413d81bf077ffe94471d6decfa44c Mon Sep 17 00:00:00 2001 From: Ritika Mishra Date: Thu, 19 Dec 2024 23:41:35 +0530 Subject: [PATCH 11/11] fixed issues occuring in deployment --- src/app/not-found.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx index 4358e61..71061c3 100644 --- a/src/app/not-found.tsx +++ b/src/app/not-found.tsx @@ -6,7 +6,7 @@ import Link from "next/link"; const FourOFourPage = async () => { return (
- +

404