diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73115d964..3382270b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,9 +131,8 @@ jobs: continue-on-error: false - name: Run tests - ## Ignoring formulus-formplayer testing for Q2 - ## run: npm test -- --coverage --watchAll=false - continue-on-error: true # We want to continue even if tests fail since tests are not set yet + run: npm test -- --coverage --watchAll=false + continue-on-error: true # Tests not fully set up yet - name: Build run: npm run build diff --git a/formulus/android/gradle.properties b/formulus/android/gradle.properties index 472490f28..b881e01bb 100644 --- a/formulus/android/gradle.properties +++ b/formulus/android/gradle.properties @@ -46,7 +46,7 @@ edgeToEdgeEnabled=false # Gradle performance optimizations (reduced for low-memory builds) org.gradle.caching=true -org.gradle.configureondemand=true +org.gradle.configureondemand=false org.gradle.daemon=true org.gradle.parallel=false org.gradle.workers.max=2 diff --git a/formulus/eslint.config.js b/formulus/eslint.config.js index ff9dc84c5..645721d3e 100644 --- a/formulus/eslint.config.js +++ b/formulus/eslint.config.js @@ -50,6 +50,8 @@ export default tseslint.config( 'error', { varsIgnorePattern: '^_', + argsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', }, ], }, diff --git a/formulus/package-lock.json b/formulus/package-lock.json index 7e1afaa78..446a0943a 100644 --- a/formulus/package-lock.json +++ b/formulus/package-lock.json @@ -73,7 +73,7 @@ "typescript-eslint": "^8.51.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@babel/code-frame": { @@ -2071,7 +2071,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" @@ -2084,7 +2084,7 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -2107,6 +2107,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -2118,6 +2119,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -2128,6 +2130,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -3250,6 +3253,7 @@ "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -3532,6 +3536,7 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, "license": "MIT", "optional": true, "engines": { @@ -4679,34 +4684,35 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -5220,6 +5226,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5233,6 +5240,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5246,6 +5254,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5259,6 +5268,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5272,6 +5282,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5285,6 +5296,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5298,6 +5310,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5311,6 +5324,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5324,6 +5338,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5337,6 +5352,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5350,6 +5366,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5363,6 +5380,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5376,6 +5394,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5389,6 +5408,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5402,6 +5422,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5415,6 +5436,7 @@ "cpu": [ "wasm32" ], + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -5431,6 +5453,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5444,6 +5467,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5457,6 +5481,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5539,7 +5564,7 @@ "version": "8.3.4", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "acorn": "^8.11.0" @@ -5679,7 +5704,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/argparse": { @@ -6866,7 +6891,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/cross-spawn": { @@ -7136,7 +7161,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "devOptional": true, + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -11265,7 +11290,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "devOptional": true, + "dev": true, "license": "ISC" }, "node_modules/makeerror": { @@ -15243,7 +15268,7 @@ "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -15420,7 +15445,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -15699,7 +15724,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/v8-to-istanbul": { @@ -16073,7 +16098,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6" diff --git a/formulus/src/components/QRScannerModal.tsx b/formulus/src/components/QRScannerModal.tsx index 06635afb7..c7ee8354a 100644 --- a/formulus/src/components/QRScannerModal.tsx +++ b/formulus/src/components/QRScannerModal.tsx @@ -42,8 +42,10 @@ interface QRScannerModalProps { // Only load QRScannerModalImpl if VisionCamera native module is linked let QRScannerModalImpl: React.ComponentType | null = null; try { + // eslint-disable-next-line @typescript-eslint/no-require-imports const { NativeModules } = require('react-native'); if (NativeModules.CameraView) { + // eslint-disable-next-line @typescript-eslint/no-require-imports QRScannerModalImpl = require('./QRScannerModalImpl').default; } } catch (e) { @@ -87,8 +89,8 @@ const QRScannerModal: React.FC = props => { - QR scanner not available. Camera module (react-native-vision-camera) is - not linked. Re-enable it in react-native.config.js and rebuild. + QR scanner not available. Camera module (react-native-vision-camera) + is not linked. Re-enable it in react-native.config.js and rebuild. Close diff --git a/formulus/src/components/QRScannerModalImpl.tsx b/formulus/src/components/QRScannerModalImpl.tsx index 76b24f699..cc2e1737b 100644 --- a/formulus/src/components/QRScannerModalImpl.tsx +++ b/formulus/src/components/QRScannerModalImpl.tsx @@ -134,7 +134,9 @@ const QRScannerModalImpl: React.FC = ({ Grant Permission - + Cancel @@ -149,7 +151,9 @@ const QRScannerModalImpl: React.FC = ({ No camera device found - + Close @@ -171,7 +175,9 @@ const QRScannerModalImpl: React.FC = ({ - {scannedData ? 'Code Scanned!' : 'Point camera at QR code or barcode'} + {scannedData + ? 'Code Scanned!' + : 'Point camera at QR code or barcode'} @@ -189,16 +195,22 @@ const QRScannerModalImpl: React.FC = ({ {scannedData} - + Scan Again - + Confirm ) : ( - + Cancel )} diff --git a/formulus/src/services/ExtensionService.ts b/formulus/src/services/ExtensionService.ts index 00dced007..ba340c5ae 100644 --- a/formulus/src/services/ExtensionService.ts +++ b/formulus/src/services/ExtensionService.ts @@ -93,11 +93,15 @@ export class ExtensionService { renderers: {}, }; - console.log(`[ExtensionService] Loading extensions for app: ${customAppPath}, form: ${formName || 'none'}`); + console.log( + `[ExtensionService] Loading extensions for app: ${customAppPath}, form: ${formName || 'none'}`, + ); // Load app-level extensions const appExtPath = `${customAppPath}/forms/ext.json`; - console.log(`[ExtensionService] Loading app-level ext.json from: ${appExtPath}`); + console.log( + `[ExtensionService] Loading app-level ext.json from: ${appExtPath}`, + ); const appLevelExt = await this.loadExtensionFile(appExtPath); if (appLevelExt) { console.log(`[ExtensionService] App-level extensions loaded:`, { @@ -106,13 +110,17 @@ export class ExtensionService { }); this.mergeExtension(result, appLevelExt); } else { - console.warn(`[ExtensionService] App-level ext.json not found or failed to load: ${appExtPath}`); + console.warn( + `[ExtensionService] App-level ext.json not found or failed to load: ${appExtPath}`, + ); } // Load form-level extensions (higher precedence) if (formName) { const formExtPath = `${customAppPath}/forms/${formName}/ext.json`; - console.log(`[ExtensionService] Loading form-level ext.json from: ${formExtPath}`); + console.log( + `[ExtensionService] Loading form-level ext.json from: ${formExtPath}`, + ); const formLevelExt = await this.loadExtensionFile(formExtPath); if (formLevelExt) { console.log(`[ExtensionService] Form-level extensions loaded:`, { @@ -152,25 +160,28 @@ export class ExtensionService { } const content = await RNFS.readFile(filePath, 'utf8'); - const rawExtension = JSON.parse(content) as any; + const rawExtension = JSON.parse(content) as Record; console.log(`[ExtensionService] Loaded ext.json from ${filePath}:`, { hasSchemas: !!rawExtension.schemas, hasDefinitions: !!rawExtension.definitions, hasFunctions: !!rawExtension.functions, - functionKeys: rawExtension.functions ? Object.keys(rawExtension.functions) : [], + functionKeys: rawExtension.functions + ? Object.keys(rawExtension.functions) + : [], hasRenderers: !!rawExtension.renderers, }); // Normalize the extension format to match ExtensionDefinition interface const extension: ExtensionDefinition = { // Handle both "schemas.definitions" and direct "definitions" - definitions: rawExtension.definitions || rawExtension.schemas?.definitions || {}, - + definitions: + rawExtension.definitions || rawExtension.schemas?.definitions || {}, + // Transform functions from {key: {path, export}} to {key: {name, module, export}} functions: rawExtension.functions ? Object.entries(rawExtension.functions).reduce( - (acc, [key, func]: [string, any]) => { + (acc, [key, func]: [string, Record]) => { acc[key] = { name: key, // Use key as name module: func.path || func.module || '', // Support both "path" and "module" @@ -181,21 +192,26 @@ export class ExtensionService { {} as Record, ) : undefined, - + // Transform renderers (similar structure) renderers: rawExtension.renderers ? Object.entries(rawExtension.renderers).reduce( - (acc, [key, renderer]: [string, any]) => { + (acc, [key, renderer]: [string, Record]) => { // Handle both flat structure and nested structure const rendererObj = renderer.renderer || renderer; const testerObj = renderer.tester || {}; - + acc[key] = { name: key, format: renderer.format || rendererObj?.format || '', - module: rendererObj?.path || rendererObj?.module || renderer.module || '', + module: + rendererObj?.path || + rendererObj?.module || + renderer.module || + '', tester: testerObj?.export || renderer.tester?.export, - renderer: rendererObj?.export || renderer.renderer?.export || key, + renderer: + rendererObj?.export || renderer.renderer?.export || key, }; return acc; }, @@ -223,11 +239,18 @@ export class ExtensionService { return extension; } catch (error) { - if ((error as any).code === 'ENOENT') { + if ( + error instanceof Error && + 'code' in error && + (error as NodeJS.ErrnoException).code === 'ENOENT' + ) { // File doesn't exist - this is OK return null; } - console.warn(`[ExtensionService] Failed to load extension file ${filePath}:`, error); + console.warn( + `[ExtensionService] Failed to load extension file ${filePath}:`, + error, + ); return null; } } diff --git a/formulus/src/services/FormService.ts b/formulus/src/services/FormService.ts index 92a5520c7..a6e24e829 100644 --- a/formulus/src/services/FormService.ts +++ b/formulus/src/services/FormService.ts @@ -271,7 +271,9 @@ export class FormService { whereClause?: string | null; }): Promise { const localRepo = databaseService.getLocalRepo(); - let observations = await localRepo.getObservationsByFormType(options.formType); + let observations = await localRepo.getObservationsByFormType( + options.formType, + ); if (options.whereClause && options.whereClause.trim()) { observations = this.filterObservationsByWhereClause( @@ -304,7 +306,10 @@ export class FormService { while ((match = dataFieldRegex.exec(whereClause)) !== null) { const field = match[1] || match[4] || match[7]; const operator = (match[2] || match[5] || match[8]).replace(/<>/g, '!='); - const value = (match[3] || match[6] || match[9] || '').replace(/''/g, "'"); + const value = (match[3] || match[6] || match[9] || '').replace( + /''/g, + "'", + ); if (field) conditions.push({ field, operator, value }); } @@ -314,7 +319,10 @@ export class FormService { while ((match = jsonExtractRegex.exec(whereClause)) !== null) { const field = match[1] || match[4] || match[7]; const operator = (match[2] || match[5] || match[8]).replace(/<>/g, '!='); - const value = (match[3] || match[6] || match[9] || '').replace(/''/g, "'"); + const value = (match[3] || match[6] || match[9] || '').replace( + /''/g, + "'", + ); if (field) conditions.push({ field, operator, value }); } @@ -330,19 +338,37 @@ export class FormService { let matches: boolean; if (isNumeric) { switch (cond.operator) { - case '=': matches = numVal === condNum; break; - case '!=': matches = numVal !== condNum; break; - case '>=': matches = numVal >= condNum; break; - case '<=': matches = numVal <= condNum; break; - case '>': matches = numVal > condNum; break; - case '<': matches = numVal < condNum; break; - default: matches = strVal === cond.value; + case '=': + matches = numVal === condNum; + break; + case '!=': + matches = numVal !== condNum; + break; + case '>=': + matches = numVal >= condNum; + break; + case '<=': + matches = numVal <= condNum; + break; + case '>': + matches = numVal > condNum; + break; + case '<': + matches = numVal < condNum; + break; + default: + matches = strVal === cond.value; } } else { switch (cond.operator) { - case '=': matches = strVal === cond.value; break; - case '!=': matches = strVal !== cond.value; break; - default: matches = false; + case '=': + matches = strVal === cond.value; + break; + case '!=': + matches = strVal !== cond.value; + break; + default: + matches = false; } } if (!matches) return false; diff --git a/formulus/src/webview/FormulusMessageHandlers.ts b/formulus/src/webview/FormulusMessageHandlers.ts index 7b5a0a9f1..b036f3eca 100644 --- a/formulus/src/webview/FormulusMessageHandlers.ts +++ b/formulus/src/webview/FormulusMessageHandlers.ts @@ -24,8 +24,15 @@ import { FormulusMessageHandlers } from './FormulusMessageHandlers.types'; // NitroSound is disabled for emulator in react-native.config.js - do not load the module // to avoid "Sound HybridObject not registered" console errors. Load lazily only when // the native module is available (re-enable in react-native.config.js and rebuild). -let NitroSound: { startRecorder: (path: string, opts: unknown) => Promise; stopRecorder: () => Promise } | null = null; -type AudioSet = { AudioSamplingRate: number; AudioEncodingBitRate: number; AudioChannels: number }; +let NitroSound: { + startRecorder: (path: string, opts: unknown) => Promise; + stopRecorder: () => Promise; +} | null = null; +type AudioSet = { + AudioSamplingRate: number; + AudioEncodingBitRate: number; + AudioChannels: number; +}; import { FormService } from '../services/FormService'; import { Observation, ObservationData } from '../database/models/Observation'; @@ -795,6 +802,7 @@ export function createFormulusMessageHandlers(): FormulusMessageHandlers { // Lazy-load NitroSound only when audio is requested (avoids console error on startup when disabled) if (!NitroSound) { try { + // eslint-disable-next-line @typescript-eslint/no-require-imports const ns = require('react-native-nitro-sound'); NitroSound = ns.default; } catch { @@ -1008,20 +1016,18 @@ export function createFormulusMessageHandlers(): FormulusMessageHandlers { //TODO: Handle deleted etc. return await service.getObservationsByFormType(formTypeString); }, - onGetObservationsByQuery: async ( - payload: { - options?: { - formType: string; - isDraft?: boolean; - includeDeleted?: boolean; - whereClause?: string | null; - }; - formType?: string; + onGetObservationsByQuery: async (payload: { + options?: { + formType: string; isDraft?: boolean; includeDeleted?: boolean; whereClause?: string | null; - }, - ) => { + }; + formType?: string; + isDraft?: boolean; + includeDeleted?: boolean; + whereClause?: string | null; + }) => { const options = (payload?.options ?? payload) as { formType: string; isDraft?: boolean; @@ -1044,7 +1050,10 @@ export function createFormulusMessageHandlers(): FormulusMessageHandlers { data.observationId ?? null, ); }, - onFormplayerInitialized: (_data: { formType?: string; status?: string }) => { + onFormplayerInitialized: (_data: { + formType?: string; + status?: string; + }) => { // Reserved for future hooks (e.g., native-side loading indicators or analytics). }, onFormulusReady: () => { diff --git a/formulus/src/webview/FormulusWebViewHandler.ts b/formulus/src/webview/FormulusWebViewHandler.ts index 17c6cb021..b04f511c6 100644 --- a/formulus/src/webview/FormulusWebViewHandler.ts +++ b/formulus/src/webview/FormulusWebViewHandler.ts @@ -303,7 +303,10 @@ export class FormulusWebViewMessageManager { pendingRequest.callbackName === 'onFormInit' ) { this.formInitRetryCount += 1; - if (this.formInitRetryCount > FormulusWebViewMessageManager.FORM_INIT_MAX_RETRIES) { + if ( + this.formInitRetryCount > + FormulusWebViewMessageManager.FORM_INIT_MAX_RETRIES + ) { console.error( `${this.logPrefix} Form init failed after ${this.formInitRetryCount} retries. Formplayer may not have loaded.`, );