From 5f8357071f93c761715d335bc37a9461449d9226 Mon Sep 17 00:00:00 2001 From: Greg Trihus Date: Fri, 9 Oct 2026 07:55:30 -0500 Subject: [PATCH 1/2] remove report --- web/eslint-report.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 web/eslint-report.json diff --git a/web/eslint-report.json b/web/eslint-report.json deleted file mode 100644 index 075deea73..000000000 --- a/web/eslint-report.json +++ /dev/null @@ -1 +0,0 @@ -[{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\app-menu.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\audioToMp3.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\auth-process.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\auth-service.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\auth-strings.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\checkMicrophonePermission.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\downloadFile.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\ffmpegBin.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\generateUUID.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\ipcMethods.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\loginState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\main\\normalizer.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unsafe-function-type","severity":2,"message":"The `Function` type accepts any function-like value.\nPrefer explicitly defining any function parameters and return type.","line":274,"column":20,"nodeType":"Identifier","messageId":"bannedFunctionType","endLine":274,"endColumn":28,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unsafe-function-type","severity":2,"message":"The `Function` type accepts any function-like value.\nPrefer explicitly defining any function parameters and return type.","line":281,"column":41,"nodeType":"Identifier","messageId":"bannedFunctionType","endLine":281,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unsafe-function-type","severity":2,"message":"The `Function` type accepts any function-like value.\nPrefer explicitly defining any function parameters and return type.","line":281,"column":57,"nodeType":"Identifier","messageId":"bannedFunctionType","endLine":281,"endColumn":65,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\electron\\preload\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\eslint.config.mjs","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\migration\\05-burrito-to-ptf.js","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":15,"column":12,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":15,"endColumn":25,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":16,"column":16,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":16,"endColumn":29,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":17,"column":14,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":17,"endColumn":29,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":18,"column":27,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":18,"endColumn":46,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":19,"column":16,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":19,"endColumn":34,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":20,"column":22,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":20,"endColumn":38,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":21,"column":32,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":21,"endColumn":76,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":23,"column":36,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":23,"endColumn":93,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":24,"column":31,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":24,"endColumn":84,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":25,"column":30,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":25,"endColumn":82,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":26,"column":35,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":26,"endColumn":91,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":27,"column":31,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":27,"endColumn":84,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\migration\\05-burrito-to-ptf.test.mjs","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\migration\\burrito-apmdata.mjs","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\migration\\usj-structure.mjs","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\migration\\usj-structure.test.mjs","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/explicit-function-return-type').","line":17,"column":1,"severity":1,"nodeType":null,"fix":{"range":[380,456],"text":" "}},{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/explicit-function-return-type').","line":22,"column":1,"severity":1,"nodeType":null,"fix":{"range":[560,636],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":2,"source":"import { test } from 'node:test';\nimport assert from 'node:assert/strict';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport {\n normalizeTextToUsj,\n extractStructureFromUsj,\n} from './usj-structure.mjs';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n/**\n * @param {string} name\n * @returns {string}\n */\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type\nfunction fixture(name) {\n return fs.readFileSync(path.join(__dirname, 'fixtures', name), 'utf-8');\n}\n\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type\nfunction pickShape(structure) {\n return {\n sections: structure.sections.map((section) => ({\n name: section.name,\n startChapter: section.startChapter,\n startVerse: section.startVerse,\n endChapter: section.endChapter,\n endVerse: section.endVerse,\n })),\n paragraphs: structure.paragraphs.map((paragraph) => ({\n sectionIndex: paragraph.sectionIndex,\n chapter: paragraph.chapter,\n startVerse: paragraph.startVerse,\n endVerse: paragraph.endVerse,\n })),\n };\n}\n\ntest('normalization parity for usfm/usx/usj structure extraction', () => {\n const usfm = normalizeTextToUsj(fixture('step2-structure.usfm'), 'usfm');\n const usx = normalizeTextToUsj(fixture('step2-structure.usx'), 'usx');\n const usj = normalizeTextToUsj(fixture('step2-structure.usj'), 'usj');\n\n const usfmShape = pickShape(extractStructureFromUsj(usfm));\n const usxShape = pickShape(extractStructureFromUsj(usx));\n const usjShape = pickShape(extractStructureFromUsj(usj));\n\n assert.deepEqual(usfmShape, usjShape);\n assert.deepEqual(usxShape, usjShape);\n});\n\ntest('section heading after \\\\c keeps ch4 audio in second section when ch4 has no verses yet', () => {\n const usfm = [\n '\\\\id RUT',\n '\\\\c 3',\n '\\\\s Ruth 3: Ruth Proposes Marriage',\n '\\\\p',\n '\\\\v 1-18 transcribe it',\n '\\\\c 4',\n '\\\\s Ruth 4: Joy',\n '\\\\p',\n ].join('\\n');\n const usj = normalizeTextToUsj(usfm, 'usfm');\n const { sections, paragraphs } = extractStructureFromUsj(usj, null);\n assert.equal(sections.length, 2);\n assert.equal(sections[1].startChapter, 4);\n assert.equal(sections[1].endChapter, 4);\n const ch4Paras = paragraphs.filter((p) => p.chapter === 4);\n assert.equal(ch4Paras.length, 0);\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\playwright.config.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\tests\\e2e\\electron.spec.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\tests\\e2e\\helpers.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\vite.config.mts","messages":[{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":1,"column":30,"nodeType":null,"messageId":"delete","endLine":1,"endColumn":31,"fix":{"range":[29,30],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":2,"column":50,"nodeType":null,"messageId":"delete","endLine":2,"endColumn":51,"fix":{"range":[80,81],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":3,"column":52,"nodeType":null,"messageId":"delete","endLine":3,"endColumn":53,"fix":{"range":[133,134],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":4,"column":42,"nodeType":null,"messageId":"delete","endLine":4,"endColumn":43,"fix":{"range":[176,177],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":5,"column":1,"nodeType":null,"messageId":"delete","endLine":5,"endColumn":2,"fix":{"range":[178,179],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":6,"column":77,"nodeType":null,"messageId":"delete","endLine":6,"endColumn":78,"fix":{"range":[256,257],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":7,"column":77,"nodeType":null,"messageId":"delete","endLine":7,"endColumn":78,"fix":{"range":[334,335],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":8,"column":38,"nodeType":null,"messageId":"delete","endLine":8,"endColumn":39,"fix":{"range":[373,374],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":9,"column":44,"nodeType":null,"messageId":"delete","endLine":9,"endColumn":45,"fix":{"range":[418,419],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":10,"column":1,"nodeType":null,"messageId":"delete","endLine":10,"endColumn":2,"fix":{"range":[420,421],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":11,"column":78,"nodeType":null,"messageId":"delete","endLine":11,"endColumn":79,"fix":{"range":[499,500],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":12,"column":79,"nodeType":null,"messageId":"delete","endLine":12,"endColumn":80,"fix":{"range":[579,580],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":13,"column":76,"nodeType":null,"messageId":"delete","endLine":13,"endColumn":77,"fix":{"range":[656,657],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":14,"column":79,"nodeType":null,"messageId":"delete","endLine":14,"endColumn":80,"fix":{"range":[736,737],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":15,"column":77,"nodeType":null,"messageId":"delete","endLine":15,"endColumn":78,"fix":{"range":[814,815],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":16,"column":58,"nodeType":null,"messageId":"delete","endLine":16,"endColumn":59,"fix":{"range":[873,874],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":17,"column":41,"nodeType":null,"messageId":"delete","endLine":17,"endColumn":42,"fix":{"range":[915,916],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":18,"column":29,"nodeType":null,"messageId":"delete","endLine":18,"endColumn":30,"fix":{"range":[945,946],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":19,"column":18,"nodeType":null,"messageId":"delete","endLine":19,"endColumn":19,"fix":{"range":[964,965],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":20,"column":72,"nodeType":null,"messageId":"delete","endLine":20,"endColumn":73,"fix":{"range":[1037,1038],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":21,"column":22,"nodeType":null,"messageId":"delete","endLine":21,"endColumn":23,"fix":{"range":[1060,1061],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":22,"column":5,"nodeType":null,"messageId":"delete","endLine":22,"endColumn":6,"fix":{"range":[1066,1067],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":23,"column":13,"nodeType":null,"messageId":"delete","endLine":23,"endColumn":14,"fix":{"range":[1080,1081],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":24,"column":43,"nodeType":null,"messageId":"delete","endLine":24,"endColumn":44,"fix":{"range":[1124,1125],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":25,"column":73,"nodeType":null,"messageId":"delete","endLine":25,"endColumn":74,"fix":{"range":[1198,1199],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":26,"column":6,"nodeType":null,"messageId":"delete","endLine":26,"endColumn":7,"fix":{"range":[1205,1206],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":27,"column":22,"nodeType":null,"messageId":"delete","endLine":27,"endColumn":23,"fix":{"range":[1228,1229],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":28,"column":5,"nodeType":null,"messageId":"delete","endLine":28,"endColumn":6,"fix":{"range":[1234,1235],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":29,"column":4,"nodeType":null,"messageId":"delete","endLine":29,"endColumn":5,"fix":{"range":[1239,1240],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":30,"column":1,"nodeType":null,"messageId":"delete","endLine":30,"endColumn":2,"fix":{"range":[1241,1242],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":31,"column":80,"nodeType":null,"messageId":"delete","endLine":31,"endColumn":81,"fix":{"range":[1322,1323],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":32,"column":81,"nodeType":null,"messageId":"delete","endLine":32,"endColumn":82,"fix":{"range":[1404,1405],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":33,"column":65,"nodeType":null,"messageId":"delete","endLine":33,"endColumn":66,"fix":{"range":[1470,1471],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":34,"column":53,"nodeType":null,"messageId":"delete","endLine":34,"endColumn":54,"fix":{"range":[1524,1525],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":35,"column":70,"nodeType":null,"messageId":"delete","endLine":35,"endColumn":71,"fix":{"range":[1595,1596],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":36,"column":1,"nodeType":null,"messageId":"delete","endLine":36,"endColumn":2,"fix":{"range":[1597,1598],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":37,"column":76,"nodeType":null,"messageId":"delete","endLine":37,"endColumn":77,"fix":{"range":[1674,1675],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":38,"column":71,"nodeType":null,"messageId":"delete","endLine":38,"endColumn":72,"fix":{"range":[1746,1747],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":39,"column":24,"nodeType":null,"messageId":"delete","endLine":39,"endColumn":25,"fix":{"range":[1771,1772],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":40,"column":18,"nodeType":null,"messageId":"delete","endLine":40,"endColumn":19,"fix":{"range":[1790,1791],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":41,"column":11,"nodeType":null,"messageId":"delete","endLine":41,"endColumn":12,"fix":{"range":[1802,1803],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":42,"column":50,"nodeType":null,"messageId":"delete","endLine":42,"endColumn":51,"fix":{"range":[1853,1854],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":43,"column":54,"nodeType":null,"messageId":"delete","endLine":43,"endColumn":55,"fix":{"range":[1908,1909],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":44,"column":5,"nodeType":null,"messageId":"delete","endLine":44,"endColumn":6,"fix":{"range":[1914,1915],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":45,"column":3,"nodeType":null,"messageId":"delete","endLine":45,"endColumn":4,"fix":{"range":[1918,1919],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":46,"column":1,"nodeType":null,"messageId":"delete","endLine":46,"endColumn":2,"fix":{"range":[1920,1921],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":47,"column":30,"nodeType":null,"messageId":"delete","endLine":47,"endColumn":31,"fix":{"range":[1951,1952],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":48,"column":17,"nodeType":null,"messageId":"delete","endLine":48,"endColumn":18,"fix":{"range":[1969,1970],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":49,"column":19,"nodeType":null,"messageId":"delete","endLine":49,"endColumn":20,"fix":{"range":[1989,1990],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":50,"column":43,"nodeType":null,"messageId":"delete","endLine":50,"endColumn":44,"fix":{"range":[2033,2034],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":51,"column":12,"nodeType":null,"messageId":"delete","endLine":51,"endColumn":13,"fix":{"range":[2046,2047],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":52,"column":16,"nodeType":null,"messageId":"delete","endLine":52,"endColumn":17,"fix":{"range":[2063,2064],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":53,"column":5,"nodeType":null,"messageId":"delete","endLine":53,"endColumn":6,"fix":{"range":[2069,2070],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":54,"column":11,"nodeType":null,"messageId":"delete","endLine":54,"endColumn":12,"fix":{"range":[2081,2082],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":55,"column":41,"nodeType":null,"messageId":"delete","endLine":55,"endColumn":42,"fix":{"range":[2123,2124],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":56,"column":23,"nodeType":null,"messageId":"delete","endLine":56,"endColumn":24,"fix":{"range":[2147,2148],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":57,"column":23,"nodeType":null,"messageId":"delete","endLine":57,"endColumn":24,"fix":{"range":[2171,2172],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":58,"column":16,"nodeType":null,"messageId":"delete","endLine":58,"endColumn":17,"fix":{"range":[2188,2189],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":59,"column":75,"nodeType":null,"messageId":"delete","endLine":59,"endColumn":76,"fix":{"range":[2264,2265],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":60,"column":72,"nodeType":null,"messageId":"delete","endLine":60,"endColumn":73,"fix":{"range":[2337,2338],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":61,"column":77,"nodeType":null,"messageId":"delete","endLine":61,"endColumn":78,"fix":{"range":[2415,2416],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":62,"column":69,"nodeType":null,"messageId":"delete","endLine":62,"endColumn":70,"fix":{"range":[2485,2486],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":63,"column":36,"nodeType":null,"messageId":"delete","endLine":63,"endColumn":37,"fix":{"range":[2522,2523],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":64,"column":9,"nodeType":null,"messageId":"delete","endLine":64,"endColumn":10,"fix":{"range":[2532,2533],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":65,"column":79,"nodeType":null,"messageId":"delete","endLine":65,"endColumn":80,"fix":{"range":[2612,2613],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":66,"column":30,"nodeType":null,"messageId":"delete","endLine":66,"endColumn":31,"fix":{"range":[2643,2644],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":67,"column":13,"nodeType":null,"messageId":"delete","endLine":67,"endColumn":14,"fix":{"range":[2657,2658],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":68,"column":29,"nodeType":null,"messageId":"delete","endLine":68,"endColumn":30,"fix":{"range":[2687,2688],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":69,"column":49,"nodeType":null,"messageId":"delete","endLine":69,"endColumn":50,"fix":{"range":[2737,2738],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":70,"column":59,"nodeType":null,"messageId":"delete","endLine":70,"endColumn":60,"fix":{"range":[2797,2798],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":71,"column":12,"nodeType":null,"messageId":"delete","endLine":71,"endColumn":13,"fix":{"range":[2810,2811],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":72,"column":18,"nodeType":null,"messageId":"delete","endLine":72,"endColumn":19,"fix":{"range":[2829,2830],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":73,"column":10,"nodeType":null,"messageId":"delete","endLine":73,"endColumn":11,"fix":{"range":[2840,2841],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":74,"column":23,"nodeType":null,"messageId":"delete","endLine":74,"endColumn":24,"fix":{"range":[2864,2865],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":75,"column":9,"nodeType":null,"messageId":"delete","endLine":75,"endColumn":10,"fix":{"range":[2874,2875],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":76,"column":7,"nodeType":null,"messageId":"delete","endLine":76,"endColumn":8,"fix":{"range":[2882,2883],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":77,"column":5,"nodeType":null,"messageId":"delete","endLine":77,"endColumn":6,"fix":{"range":[2888,2889],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":78,"column":13,"nodeType":null,"messageId":"delete","endLine":78,"endColumn":14,"fix":{"range":[2902,2903],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":79,"column":13,"nodeType":null,"messageId":"delete","endLine":79,"endColumn":14,"fix":{"range":[2916,2917],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":80,"column":23,"nodeType":null,"messageId":"delete","endLine":80,"endColumn":24,"fix":{"range":[2940,2941],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":81,"column":15,"nodeType":null,"messageId":"delete","endLine":81,"endColumn":16,"fix":{"range":[2956,2957],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":82,"column":14,"nodeType":null,"messageId":"delete","endLine":82,"endColumn":15,"fix":{"range":[2971,2972],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":83,"column":63,"nodeType":null,"messageId":"delete","endLine":83,"endColumn":64,"fix":{"range":[3035,3036],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":84,"column":72,"nodeType":null,"messageId":"delete","endLine":84,"endColumn":73,"fix":{"range":[3108,3109],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":85,"column":29,"nodeType":null,"messageId":"delete","endLine":85,"endColumn":30,"fix":{"range":[3138,3139],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":86,"column":74,"nodeType":null,"messageId":"delete","endLine":86,"endColumn":75,"fix":{"range":[3213,3214],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":87,"column":74,"nodeType":null,"messageId":"delete","endLine":87,"endColumn":75,"fix":{"range":[3288,3289],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":88,"column":75,"nodeType":null,"messageId":"delete","endLine":88,"endColumn":76,"fix":{"range":[3364,3365],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":89,"column":31,"nodeType":null,"messageId":"delete","endLine":89,"endColumn":32,"fix":{"range":[3396,3397],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":90,"column":58,"nodeType":null,"messageId":"delete","endLine":90,"endColumn":59,"fix":{"range":[3455,3456],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":91,"column":42,"nodeType":null,"messageId":"delete","endLine":91,"endColumn":43,"fix":{"range":[3498,3499],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":92,"column":35,"nodeType":null,"messageId":"delete","endLine":92,"endColumn":36,"fix":{"range":[3534,3535],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":93,"column":47,"nodeType":null,"messageId":"delete","endLine":93,"endColumn":48,"fix":{"range":[3582,3583],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":94,"column":46,"nodeType":null,"messageId":"delete","endLine":94,"endColumn":47,"fix":{"range":[3629,3630],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":95,"column":66,"nodeType":null,"messageId":"delete","endLine":95,"endColumn":67,"fix":{"range":[3696,3697],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":96,"column":41,"nodeType":null,"messageId":"delete","endLine":96,"endColumn":42,"fix":{"range":[3738,3739],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":97,"column":11,"nodeType":null,"messageId":"delete","endLine":97,"endColumn":12,"fix":{"range":[3750,3751],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":98,"column":9,"nodeType":null,"messageId":"delete","endLine":98,"endColumn":10,"fix":{"range":[3760,3761],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":99,"column":17,"nodeType":null,"messageId":"delete","endLine":99,"endColumn":18,"fix":{"range":[3778,3779],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":100,"column":78,"nodeType":null,"messageId":"delete","endLine":100,"endColumn":79,"fix":{"range":[3857,3858],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":101,"column":29,"nodeType":null,"messageId":"delete","endLine":101,"endColumn":30,"fix":{"range":[3887,3888],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":102,"column":9,"nodeType":null,"messageId":"delete","endLine":102,"endColumn":10,"fix":{"range":[3897,3898],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":103,"column":8,"nodeType":null,"messageId":"delete","endLine":103,"endColumn":9,"fix":{"range":[3906,3907],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":104,"column":5,"nodeType":null,"messageId":"delete","endLine":104,"endColumn":6,"fix":{"range":[3912,3913],"text":""}},{"ruleId":"prettier/prettier","severity":1,"message":"Delete `␍`","line":105,"column":4,"nodeType":null,"messageId":"delete","endLine":105,"endColumn":5,"fix":{"range":[3917,3918],"text":""}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":105,"fixableErrorCount":0,"fixableWarningCount":105,"source":"import path from 'node:path';\r\nimport { defineConfig, type Plugin } from 'vite';\r\nimport electron from 'vite-plugin-electron/simple';\r\nimport react from '@vitejs/plugin-react';\r\n\r\n// Electron app build. The renderer source lives in the web package (./web),\r\n// which also builds standalone for the web with its own web/vite.config.ts.\r\nconst repoRoot = import.meta.dirname;\r\nconst webRoot = path.join(repoRoot, 'web');\r\n\r\n// `virtual:pwa-register` is provided by vite-plugin-pwa, which is only wired\r\n// into the web build (web/vite.config.ts). The shared renderer source imports\r\n// it in PwaUpdatePrompt.tsx, but that component is mounted only on the web\r\n// (see Root.tsx: `{!isElectron && ...}`), so the import is never evaluated in\r\n// Electron. Stub the virtual module here so neither the dev server's import\r\n// analysis nor the production build fails to resolve it.\r\nconst pwaRegisterStub = (): Plugin => ({\r\n name: 'pwa-register-stub',\r\n resolveId(id) {\r\n if (id === 'virtual:pwa-register') return '\\0virtual:pwa-register';\r\n return undefined;\r\n },\r\n load(id) {\r\n if (id === '\\0virtual:pwa-register') {\r\n return 'export const registerSW = () => () => Promise.resolve();';\r\n }\r\n return undefined;\r\n },\r\n});\r\n\r\n// Main-process dependencies are loaded from node_modules at runtime (keytar is\r\n// native; ffmpeg-static/ffprobe-static resolve binaries next to themselves), so\r\n// bundle only local files and externalize every package import.\r\nconst externalizePackages = (id: string): boolean =>\r\n !(id.startsWith('.') || id.startsWith('/') || path.isAbsolute(id));\r\n\r\n// main/preload are built in their own Vite instances; pin them to the repo\r\n// root so their output lands in /dist-electron, not /web.\r\nconst electronBuild = {\r\n root: repoRoot,\r\n build: {\r\n outDir: path.join(repoRoot, 'dist-electron'),\r\n rollupOptions: { external: externalizePackages },\r\n },\r\n};\r\n\r\nexport default defineConfig({\r\n root: webRoot,\r\n envDir: webRoot,\r\n publicDir: path.join(webRoot, 'public'),\r\n server: {\r\n port: 3000,\r\n },\r\n build: {\r\n outDir: path.join(repoRoot, 'dist'),\r\n emptyOutDir: true,\r\n rolldownOptions: {\r\n output: {\r\n // Rolldown splits the renderer into chunks that import each other\r\n // (e.g. utils <-> StyledBox). Without this, a chunk can call a\r\n // CommonJS wrapper (React's) from another chunk before that chunk's\r\n // body has run: \"Uncaught TypeError: So is not a function\".\r\n strictExecutionOrder: true,\r\n },\r\n // eng-vrs.ts is intentionally both statically and dynamically imported.\r\n onwarn(warning, warn) {\r\n if (\r\n warning.message &&\r\n warning.message.includes('eng-vrs') &&\r\n warning.message.includes('dynamically imported')\r\n ) {\r\n return;\r\n }\r\n warn(warning);\r\n },\r\n },\r\n },\r\n plugins: [\r\n react(),\r\n pwaRegisterStub(),\r\n electron({\r\n main: {\r\n // Object form names the output dist-electron/main.js.\r\n entry: { main: path.join(repoRoot, 'electron/main/index.ts') },\r\n vite: electronBuild,\r\n // launch.json sets REMOTE_DEBUGGING_PORT; the plugin ignores it.\r\n // js-debug also injects NODE_OPTIONS into this process. Electron\r\n // inherits that bootloader and pauses before the window stays up.\r\n onstart({ startup }) {\r\n const port = process.env.REMOTE_DEBUGGING_PORT;\r\n const env = { ...process.env };\r\n delete env.NODE_OPTIONS;\r\n delete env.VSCODE_INSPECTOR_OPTIONS;\r\n const argv = ['.', '--no-sandbox'];\r\n if (port) argv.push(`--remote-debugging-port=${port}`);\r\n return startup(argv, { env });\r\n },\r\n },\r\n preload: {\r\n input: { preload: path.join(repoRoot, 'electron/preload/index.ts') },\r\n vite: electronBuild,\r\n },\r\n }),\r\n ],\r\n});\r\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\__mocks__\\api-variable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\__mocks__\\fileMock.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\api-variable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\cypress.config.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":6,"column":5,"severity":1,"nodeType":null,"fix":{"range":[107,168],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { defineConfig } from 'cypress';\n\nexport default defineConfig({\n projectId: 'atwo4k',\n e2e: {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n setupNodeEvents(_on, _config) {\n // implement node event listeners here\n },\n },\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\jest-pact.config.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\jest.config.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\jest.setup.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\jest.smoke.config.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\App.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\Sources.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\FaithbridgeIframe.test.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":77,"column":5,"severity":1,"nodeType":null,"fix":{"range":[2506,2567],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import React, { PropsWithChildren } from 'react';\nimport '@testing-library/jest-dom';\nimport { render, screen, fireEvent, waitFor } from '@testing-library/react';\nimport { FaithbridgeIframe } from '../components/PassageDetail/Internalization/FaithbridgeIframe';\nimport type { FaithbridgeData } from '../components/PassageDetail/Internalization/useFaithbridgeResult';\nimport { TokenContext } from '../context/TokenProvider';\nimport { useFaithbridgeResult } from '../components/PassageDetail/Internalization/useFaithbridgeResult';\nimport usePassageDetailContext from '../context/usePassageDetailContext';\nimport { useRole } from '../crud';\nimport { remoteId } from '../crud';\nimport { generateUUID } from '../utils';\nimport { logError } from '../utils';\nimport { axiosGet } from '../utils/axios';\n\n// Mock @auth0/auth0-react\njest.mock('@auth0/auth0-react', () => ({\n useAuth0: jest.fn(() => ({\n getAccessTokenSilently: jest.fn(() => Promise.resolve('mock-token')),\n loginWithRedirect: jest.fn(() => Promise.resolve()),\n user: {\n email: 'test@example.com',\n email_verified: true,\n sub: 'auth0|123',\n },\n isLoading: false,\n isAuthenticated: false,\n error: undefined,\n })),\n User: {},\n RedirectLoginOptions: {},\n}));\n\n// The control barrel pulls in the Sheet/store graph (and react-localization's\n// ESM build, which Jest can't parse), so stub the pieces this component uses.\njest.mock('../control', () => ({\n Button: ({ children, ...props }: any) => (\n \n ),\n ActionRow: ({ children }: PropsWithChildren) =>
{children}
,\n GrowingSpacer: () =>
,\n // rowSx is a theme callback needing the app theme augmentation; the plain\n // object keeps the Box happy without a ThemeProvider.\n rowSx: {},\n}));\n\n// Mock schema to avoid import.meta issues in Jest\nconst mockMemory = {\n cache: {\n query: jest.fn(() => []),\n },\n update: jest.fn(),\n keyMap: {\n user: {\n 'user-123': 'remote-user-123',\n },\n },\n};\n\njest.mock('../schema', () => ({\n memory: mockMemory,\n requestedSchema: 100,\n}));\n\nlet mockUser: string | null = 'user-123';\nlet mockHasPermission = true;\nlet mockRef = 'MAT 1:1-5';\nlet mockIsMobileWidth = false;\n\n// Mock dependencies\njest.mock('../utils', () => ({\n generateUUID: jest.fn(() => 'mock-uuid-123'),\n useCheckOnline: () => (callback: (result: boolean) => void) => {\n // Simulate online check by calling the callback with true\n callback(true);\n },\n logError: jest.fn(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n (_severity: number, _reporter: any, _error: Error | string) => {}\n ),\n Severity: { error: 1 },\n useMobile: () => ({\n isMobile: mockIsMobileWidth,\n isMobileView: false,\n isMobileWidth: mockIsMobileWidth,\n }),\n}));\n\njest.mock(\n '../components/PassageDetail/Internalization/useFaithbridgeResult',\n () => ({\n useFaithbridgeResult: jest.fn(),\n })\n);\n\njest.mock('../context/usePassageDetailContext', () => ({\n __esModule: true,\n default: jest.fn(),\n}));\n\njest.mock('../crud', () => ({\n remoteId: jest.fn(() => 'remote-user-123'),\n useRole: jest.fn(() => ({ userIsAdmin: false })),\n}));\n\njest.mock('../assets/brands', () => ({\n FaithBridge: 'FaithBridge',\n}));\n\n// Mock GlobalContext to avoid context errors\njest.mock('../context/useGlobal', () => ({\n useGlobal: jest.fn((key: string) => {\n const mockValues: Record = {\n memory: mockMemory,\n user: mockUser,\n offline: false,\n connected: true,\n offlineOnly: false,\n errorReporter: {\n notify: jest.fn(),\n },\n };\n return [mockValues[key], jest.fn()];\n }),\n useGetGlobal: jest.fn(() =>\n jest.fn((key: string) => {\n const mockValues: Record = {\n memory: mockMemory,\n user: mockUser,\n offline: false,\n };\n return mockValues[key];\n })\n ),\n}));\n\n// Mock GlobalContext\njest.mock('../context/GlobalContext', () => ({\n GlobalContext: React.createContext({\n globalState: {},\n setGlobalState: jest.fn(),\n }),\n}));\n\njest.mock('react-redux', () => ({\n useSelector: () => ({\n addContent: 'Add Content as Resource',\n audioResources: 'Request Audio',\n newChat: 'New Chat',\n loading: 'Loading result...',\n error: 'Error: ',\n noInfo: 'No information found',\n audio: 'audio',\n text: 'text',\n }),\n shallowEqual: jest.fn(),\n}));\n\njest.mock('../utils/useStepPermission', () => ({\n useStepPermissions: () => ({\n canDoSectionStep: jest.fn().mockReturnValue(mockHasPermission),\n }),\n}));\n\njest.mock('../utils/axios', () => ({\n axiosGet: jest.fn(),\n}));\n\njest.mock('../components/PassageDetail/Internalization/usePassageRef', () => ({\n usePassageRef: () => {\n return {\n passageRef: jest.fn().mockReturnValue(mockRef),\n shortBook: jest.fn().mockReturnValue('MAT'),\n };\n },\n}));\n\n// Mock the useFaithbridgeResult hook\nconst mockUseFaithbridgeResult = useFaithbridgeResult as jest.MockedFunction<\n typeof useFaithbridgeResult\n>;\n\n// Mock the usePassageDetailContext hook\nconst mockUsePassageDetailContext =\n usePassageDetailContext as jest.MockedFunction<\n typeof usePassageDetailContext\n >;\n\n// Mock the useRole hook\nconst mockUseRole = useRole as jest.MockedFunction;\n\n// Mock the remoteId function\nconst mockRemoteId = remoteId as jest.MockedFunction;\n\n// Mock the generateUUID function\nconst mockGenerateUUID = generateUUID as jest.MockedFunction<\n typeof generateUUID\n>;\n// Mock the logError function\nconst mockLogError = logError as jest.MockedFunction;\n\n// Now you can set the mock implementation in your tests:\nconst mockAxiosGet = axiosGet as jest.MockedFunction;\n\n// Mock passage data\nconst mockPassage = {\n type: 'passage',\n id: 'passage-123',\n attributes: {\n sequencenum: 1,\n book: 'MAT',\n reference: '1:1-5',\n state: 'draft',\n hold: false,\n title: 'Test Passage',\n lastComment: '',\n stepComplete: '',\n dateCreated: '2024-01-01T00:00:00Z',\n dateUpdated: '2024-01-01T00:00:00Z',\n lastModifiedBy: 1,\n },\n} as any;\n\nconst mockTokenValue = { state: { accessToken: 'mock-access-token' } };\n\nconst wrapper = (children: React.ReactNode) =>\n render(\n \n {children}\n \n );\n\ndescribe('FaithbridgeIframe', () => {\n let mockOnMarkdown: jest.Mock;\n let mockOnClose: jest.Mock;\n let mockFetchResult: jest.Mock;\n\n beforeEach(() => {\n mockOnMarkdown = jest.fn();\n mockOnClose = jest.fn();\n mockFetchResult = jest.fn();\n\n // Reset all mocks\n jest.clearAllMocks();\n\n // Setup default mock implementations\n mockUsePassageDetailContext.mockReturnValue({\n passage: mockPassage,\n } as any);\n\n mockUseFaithbridgeResult.mockReturnValue({\n data: null,\n loading: false,\n error: null,\n fetchResult: mockFetchResult,\n });\n\n mockAxiosGet.mockReset();\n mockAxiosGet.mockReturnValue({\n name: 'aquifer-name',\n grouping: { name: 'aquifer-grouping' },\n } as any);\n\n mockUseRole.mockReturnValue({ userIsAdmin: false } as any);\n mockRemoteId.mockReturnValue('remote-user-123');\n mockGenerateUUID.mockReturnValue('mock-uuid-123');\n mockHasPermission = true;\n mockRef = 'MAT 1:1-5';\n mockIsMobileWidth = false;\n });\n\n describe('initialization', () => {\n it('should render the iframe with correct URL parameters', () => {\n wrapper(\n \n );\n\n const iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toBeInTheDocument();\n expect(iframe).toHaveAttribute(\n 'src',\n 'https://faithbridge.multilingualai.com/apm?chatSessionId=mock-uuid-123&verseRef=MAT+1%3A1-5&userId=remote-user-123'\n );\n expect(iframe).toHaveAttribute(\n 'style',\n 'width: 100%; height: 600px; display: block; overflow: hidden;'\n );\n expect(iframe).toHaveAttribute('allowFullScreen');\n });\n\n it('should generate a new chat ID on mount', () => {\n wrapper(\n \n );\n\n expect(mockGenerateUUID).toHaveBeenCalledTimes(1);\n });\n\n it('should set verse reference from passage data', () => {\n wrapper(\n \n );\n\n // The iframe src should contain the verse reference\n const iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toHaveAttribute(\n 'src',\n expect.stringContaining('verseRef=MAT+1%3A1-5')\n );\n });\n\n it('should use default values when passage data is missing', () => {\n mockUsePassageDetailContext.mockReturnValue({\n passage: null,\n } as any);\n\n wrapper(\n \n );\n\n const iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toBeInTheDocument();\n expect(iframe).toHaveAttribute(\n 'src',\n expect.stringContaining('verseRef=MAT+1%3A1')\n );\n });\n });\n\n describe('button interactions', () => {\n it('should render New Chat button with correct text', () => {\n wrapper(\n \n );\n\n const newChatButton = screen.getByText('New Chat');\n expect(newChatButton).toBeInTheDocument();\n });\n\n it('should generate new chat ID when New Chat button is clicked', () => {\n wrapper(\n \n );\n\n const newChatButton = screen.getByText('New Chat');\n fireEvent.click(newChatButton);\n\n expect(mockGenerateUUID).toHaveBeenCalledTimes(2); // Once on mount, once on click\n });\n\n it('should not render Add Content button for users without permission', () => {\n mockHasPermission = false;\n mockUseRole.mockReturnValue({ userIsAdmin: false } as any);\n\n wrapper(\n \n );\n\n expect(\n screen.queryByText('Add Content as Resource')\n ).not.toBeInTheDocument();\n });\n\n it('should hide audio checkbox and Add Content when isMobileWidth is true', () => {\n mockIsMobileWidth = true;\n\n wrapper(\n \n );\n\n expect(screen.getByText('New Chat')).toBeInTheDocument();\n expect(screen.queryByText('Request Audio')).not.toBeInTheDocument();\n expect(\n screen.queryByText('Add Content as Resource')\n ).not.toBeInTheDocument();\n });\n\n it('should render Add Content button for admin users', () => {\n mockUseRole.mockReturnValue({ userIsAdmin: true } as any);\n\n wrapper(\n \n );\n\n const addContentButton = screen.getByText('Add Content as Resource');\n expect(addContentButton).toBeInTheDocument();\n });\n\n it('should call fetchResult when Add Content button is clicked by admin', () => {\n mockUseRole.mockReturnValue({ userIsAdmin: true } as any);\n\n wrapper(\n \n );\n\n const addContentButton = screen.getByText('Add Content as Resource');\n fireEvent.click(addContentButton);\n\n expect(mockFetchResult).toHaveBeenCalledWith(\n 'mock-uuid-123',\n 'remote-user-123',\n true\n );\n });\n\n it('should not call fetchResult when Add Content button is clicked without required data', () => {\n mockUseRole.mockReturnValue({ userIsAdmin: true } as any);\n mockUsePassageDetailContext.mockReturnValue({\n passage: null,\n } as any);\n // Mock userId to be null to actually prevent fetchResult from being called\n mockUser = null;\n\n wrapper(\n \n );\n\n const addContentButton = screen.getByText('Add Content as Resource');\n fireEvent.click(addContentButton);\n\n expect(mockFetchResult).not.toHaveBeenCalled();\n\n // Restore the original mock\n mockUser = 'user-123';\n });\n });\n\n describe('loading and error states', () => {\n it('should show loading message when loading is true', () => {\n mockUseFaithbridgeResult.mockReturnValue({\n data: null,\n loading: true,\n error: null,\n fetchResult: mockFetchResult,\n });\n\n wrapper(\n \n );\n\n expect(screen.getByText('Loading result...')).toBeInTheDocument();\n });\n\n it('should show error message when error is present', () => {\n mockUseFaithbridgeResult.mockReturnValue({\n data: null,\n loading: false,\n error: 'Network error occurred',\n fetchResult: mockFetchResult,\n });\n\n wrapper(\n \n );\n\n expect(\n screen.getByText('Error: Network error occurred')\n ).toBeInTheDocument();\n });\n\n it('should show 500 error message when iframe fails with server error', () => {\n mockUseFaithbridgeResult.mockReturnValue({\n data: null,\n loading: false,\n error: 'HTTP 500: Internal Server Error',\n fetchResult: mockFetchResult,\n });\n\n wrapper(\n \n );\n\n expect(\n screen.getByText('Error: HTTP 500: Internal Server Error')\n ).toBeInTheDocument();\n });\n\n it('should handle 500 error with retry mechanism', () => {\n // Simulate multiple errors to trigger the retry limit\n mockUseFaithbridgeResult.mockReturnValue({\n data: null,\n loading: false,\n error: 'HTTP 500: Internal Server Error',\n fetchResult: mockFetchResult,\n });\n\n const { rerender } = wrapper(\n \n );\n\n // Simulate 5 consecutive errors to reach the retry limit\n for (let i = 0; i < 5; i++) {\n mockUseFaithbridgeResult.mockReturnValue({\n data: null,\n loading: false,\n error: `HTTP 500: Internal Server Error (attempt ${i + 1})`,\n fetchResult: mockFetchResult,\n });\n\n rerender(\n \n \n \n );\n }\n\n // After 5 errors, logError should be called\n expect(mockLogError).toHaveBeenCalledWith(\n 1,\n { notify: expect.any(Function) },\n 'HTTP 500: Internal Server Error (attempt 5)'\n );\n });\n\n it('should handle 500 error state properly', () => {\n mockUseFaithbridgeResult.mockReturnValue({\n data: null,\n loading: false,\n error: 'HTTP 500: Internal Server Error - Database connection failed',\n fetchResult: mockFetchResult,\n });\n\n wrapper(\n \n );\n\n // Verify the error is displayed\n expect(\n screen.getByText(\n 'Error: HTTP 500: Internal Server Error - Database connection failed'\n )\n ).toBeInTheDocument();\n\n // Verify the iframe is still rendered (component doesn't crash)\n const iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toBeInTheDocument();\n });\n\n it('should handle multiple 500 errors and show latest error message', () => {\n const { rerender } = wrapper(\n \n );\n\n // First error\n mockUseFaithbridgeResult.mockReturnValue({\n data: null,\n loading: false,\n error: 'HTTP 500: Internal Server Error - First attempt',\n fetchResult: mockFetchResult,\n });\n\n rerender(\n \n \n \n );\n\n expect(\n screen.getByText(\n 'Error: HTTP 500: Internal Server Error - First attempt'\n )\n ).toBeInTheDocument();\n\n // Second error\n mockUseFaithbridgeResult.mockReturnValue({\n data: null,\n loading: false,\n error: 'HTTP 500: Internal Server Error - Second attempt',\n fetchResult: mockFetchResult,\n });\n\n rerender(\n \n \n \n );\n\n expect(\n screen.getByText(\n 'Error: HTTP 500: Internal Server Error - Second attempt'\n )\n ).toBeInTheDocument();\n });\n\n it('should display 500 error message correctly in UI', () => {\n mockUseFaithbridgeResult.mockReturnValue({\n data: null,\n loading: false,\n error:\n 'HTTP 500: Internal Server Error - Server is temporarily unavailable',\n fetchResult: mockFetchResult,\n });\n\n wrapper(\n \n );\n\n expect(\n screen.getByText(\n 'Error: HTTP 500: Internal Server Error - Server is temporarily unavailable'\n )\n ).toBeInTheDocument();\n });\n\n it('should not show loading or error messages when both are false/null', () => {\n mockUseFaithbridgeResult.mockReturnValue({\n data: null,\n loading: false,\n error: null,\n fetchResult: mockFetchResult,\n });\n\n wrapper(\n \n );\n\n expect(screen.queryByText('Loading result...')).not.toBeInTheDocument();\n expect(screen.queryByText(/Error:/)).not.toBeInTheDocument();\n });\n });\n\n describe('data handling', () => {\n it('should call onMarkdown with data audioUrl when data is received and audio is true', async () => {\n const mockData: FaithbridgeData = {\n chatSessionId: 'chat-123',\n messages: [\n {\n content: 'My sample query',\n language: 'ENG',\n messageType: 'USER',\n sources: [],\n timestamp: '2024-01-01T00:00:00Z',\n },\n {\n audioUrl: 'https://example.com/audio.mp3',\n content: 'Sample translation content',\n language: 'ENG',\n messageType: 'BOT',\n sources: [],\n timestamp: '2024-01-01T00:00:00Z',\n },\n ],\n };\n\n mockUseFaithbridgeResult.mockReturnValue({\n data: mockData,\n loading: false,\n error: null,\n fetchResult: mockFetchResult,\n });\n\n wrapper(\n \n );\n\n await waitFor(() => {\n expect(mockOnMarkdown).toHaveBeenCalledWith(\n mockData.messages[0].content,\n mockData.messages[1].audioUrl,\n mockData.messages[1].content\n );\n });\n });\n\n it('should call onMarkdown with data content when data is received and audio is false', async () => {\n const mockData: FaithbridgeData = {\n chatSessionId: 'chat-123',\n messages: [\n {\n content: 'My sample query',\n language: 'ENG',\n messageType: 'USER',\n sources: [],\n timestamp: '2024-01-01T00:00:00Z',\n },\n {\n content: 'Sample translation content',\n language: 'ENG',\n messageType: 'BOT',\n sources: [],\n timestamp: '2024-01-01T00:00:00Z',\n },\n ],\n };\n\n mockUseFaithbridgeResult.mockReturnValue({\n data: mockData,\n loading: false,\n error: null,\n fetchResult: mockFetchResult,\n });\n\n wrapper(\n \n );\n\n const audioButton = screen.getByText('Request Audio');\n fireEvent.click(audioButton);\n\n await waitFor(() => {\n expect(mockOnMarkdown).toHaveBeenCalledWith(\n mockData.messages[0].content,\n '',\n mockData.messages[1].content\n );\n });\n });\n\n it('should call onClose when data is received', async () => {\n const mockData: FaithbridgeData = {\n chatSessionId: 'chat-123',\n messages: [\n {\n content: 'Sample translation content',\n language: 'ENG',\n messageType: 'BOT',\n sources: [],\n timestamp: '2024-01-01T00:00:00Z',\n },\n ],\n };\n\n mockUseFaithbridgeResult.mockReturnValue({\n data: mockData,\n loading: false,\n error: null,\n fetchResult: mockFetchResult,\n });\n\n wrapper(\n \n );\n\n await waitFor(() => {\n expect(mockOnClose).toHaveBeenCalled();\n });\n });\n\n it('should handle data without messages content', async () => {\n // Provide an empty messages array to simulate missing lastMessage\n const mockData: FaithbridgeData = {\n chatSessionId: 'chat-123',\n messages: [],\n };\n\n mockUseFaithbridgeResult.mockReturnValue({\n data: mockData,\n loading: false,\n error: null,\n fetchResult: mockFetchResult,\n });\n\n wrapper(\n \n );\n\n await waitFor(() => {\n expect(mockOnMarkdown).toHaveBeenCalledWith('', '', '');\n });\n });\n\n it('should not call callbacks when onClose are not provided', async () => {\n const mockData: FaithbridgeData = {\n chatSessionId: 'chat-123',\n messages: [\n {\n content: 'Sample translation content',\n language: 'ENG',\n messageType: 'BOT',\n sources: [],\n timestamp: '2024-01-01T00:00:00Z',\n },\n ],\n };\n\n mockUseFaithbridgeResult.mockReturnValue({\n data: mockData,\n loading: false,\n error: null,\n fetchResult: mockFetchResult,\n });\n\n wrapper();\n\n // Should not throw any errors\n await waitFor(() => {\n expect(true).toBe(true); // Just ensure the component renders without errors\n });\n });\n });\n\n describe('URL parameter construction', () => {\n it('should construct URL with all required parameters', () => {\n wrapper(\n \n );\n\n const iframe = screen.getByTitle('FaithBridge');\n const src = iframe.getAttribute('src');\n\n expect(src).toContain('chatSessionId=mock-uuid-123');\n expect(src).toContain('verseRef=MAT+1%3A1-5');\n expect(src).toContain('userId=remote-user-123');\n });\n\n it('should handle special characters in verse reference', () => {\n mockUsePassageDetailContext.mockReturnValue({\n passage: {\n type: 'passage',\n id: 'passage-123',\n attributes: {\n book: 'MAT',\n reference: '1:1-5; 10-15',\n } as any,\n },\n } as any);\n mockRef = 'MAT 1:1-5; 10-15';\n\n wrapper(\n \n );\n\n const iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toHaveAttribute(\n 'src',\n expect.stringContaining('verseRef=MAT+1%3A1-5%3B+10-15')\n );\n });\n\n it('should handle missing user remote ID', () => {\n mockRemoteId.mockReturnValue(null as any);\n\n wrapper(\n \n );\n\n const iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toHaveAttribute('src', expect.stringContaining('userId='));\n });\n });\n\n describe('state updates', () => {\n it('should update iframe src when chat ID changes', () => {\n wrapper(\n \n );\n\n // First render\n let iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toHaveAttribute(\n 'src',\n expect.stringContaining('chatSessionId=mock-uuid-123')\n );\n\n // Change the mock to return a different UUID\n mockGenerateUUID.mockReturnValue('mock-uuid-456');\n\n // Trigger a re-render by clicking New Chat\n const newChatButton = screen.getByText('New Chat');\n fireEvent.click(newChatButton);\n\n // Check that the iframe src was updated\n iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toHaveAttribute(\n 'src',\n expect.stringContaining('chatSessionId=mock-uuid-456')\n );\n });\n\n it('should update iframe src when verse reference changes', () => {\n const { rerender } = wrapper(\n \n );\n\n // First render\n let iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toHaveAttribute(\n 'src',\n expect.stringContaining('verseRef=MAT+1%3A1-5')\n );\n\n // Update passage data\n mockUsePassageDetailContext.mockReturnValue({\n passage: {\n type: 'passage',\n id: 'passage-456',\n attributes: {\n book: 'JHN',\n reference: '3:16',\n } as any,\n },\n } as any);\n mockRef = 'JHN 3:16';\n\n // Re-render with new passage data\n rerender(\n \n \n \n );\n\n // Check that the iframe src was updated\n iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toHaveAttribute(\n 'src',\n expect.stringContaining('verseRef=JHN+3%3A16')\n );\n });\n });\n\n describe('edge cases', () => {\n it('should handle missing passage data gracefully', () => {\n mockUsePassageDetailContext.mockReturnValue({\n passage: null,\n } as any);\n\n wrapper(\n \n );\n\n const iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toBeInTheDocument();\n expect(iframe).toHaveAttribute(\n 'src',\n expect.stringContaining('verseRef=MAT+1%3A1')\n );\n });\n\n it('should handle missing passage attributes gracefully', () => {\n mockUsePassageDetailContext.mockReturnValue({\n passage: {\n type: 'passage',\n id: 'passage-123',\n attributes: {} as any,\n },\n } as any);\n\n wrapper(\n \n );\n\n const iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toBeInTheDocument();\n expect(iframe).toHaveAttribute(\n 'src',\n expect.stringContaining('verseRef=MAT+1%3A1')\n );\n });\n\n it('should handle missing global context data', () => {\n wrapper(\n \n );\n\n const iframe = screen.getByTitle('FaithBridge');\n expect(iframe).toBeInTheDocument();\n });\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\ProjectResourceConfigure.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'MediaFileD' is defined but never used. Allowed unused vars must match /^_/u.","line":6,"column":21,"nodeType":null,"messageId":"unusedVar","endLine":6,"endColumn":31,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'arg' is defined but never used. Allowed unused args must match /^_/u.","line":121,"column":24,"nodeType":null,"messageId":"unusedVar","endLine":121,"endColumn":27,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\generateUUID.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\getSheet.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'psg' is defined but never used. Allowed unused args must match /^_/u.","line":217,"column":29,"nodeType":null,"messageId":"unusedVar","endLine":217,"endColumn":32,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'step' is defined but never used. Allowed unused args must match /^_/u.","line":217,"column":42,"nodeType":null,"messageId":"unusedVar","endLine":217,"endColumn":46,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'publishTo' is defined but never used. Allowed unused args must match /^_/u.","line":309,"column":23,"nodeType":null,"messageId":"unusedVar","endLine":309,"endColumn":32,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'rec' is defined but never used. Allowed unused args must match /^_/u.","line":317,"column":22,"nodeType":null,"messageId":"unusedVar","endLine":317,"endColumn":25,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'ref' is defined but never used. Allowed unused args must match /^_/u.","line":317,"column":46,"nodeType":null,"messageId":"unusedVar","endLine":317,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'passageId' is defined but never used. Allowed unused args must match /^_/u.","line":318,"column":29,"nodeType":null,"messageId":"unusedVar","endLine":318,"endColumn":38,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'destinations' is defined but never used. Allowed unused args must match /^_/u.","line":322,"column":24,"nodeType":null,"messageId":"unusedVar","endLine":322,"endColumn":36,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'passage' is defined but never used. Allowed unused args must match /^_/u.","line":324,"column":28,"nodeType":null,"messageId":"unusedVar","endLine":324,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\getWhereis.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'cmd' is defined but never used. Allowed unused args must match /^_/u.","line":7,"column":22,"nodeType":null,"messageId":"unusedVar","endLine":7,"endColumn":25,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'args' is defined but never used. Allowed unused args must match /^_/u.","line":7,"column":35,"nodeType":null,"messageId":"unusedVar","endLine":7,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'opts' is defined but never used. Allowed unused args must match /^_/u.","line":7,"column":52,"nodeType":null,"messageId":"unusedVar","endLine":7,"endColumn":56,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'reject' is defined but never used. Allowed unused args must match /^_/u.","line":8,"column":41,"nodeType":null,"messageId":"unusedVar","endLine":8,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\isSectionOrPassageRow.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\refMatch.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\refilterSheet.assignedToMe.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\shtColumnHeads.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\shtNumChanges.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\shtResequence.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\useFaithbridgeResult.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\useSheetLocalSave.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":2,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":2,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'val' is defined but never used. Allowed unused args must match /^_/u.","line":98,"column":32,"nodeType":null,"messageId":"unusedVar","endLine":98,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'val' is defined but never used. Allowed unused args must match /^_/u.","line":149,"column":32,"nodeType":null,"messageId":"unusedVar","endLine":149,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'val' is defined but never used. Allowed unused args must match /^_/u.","line":190,"column":32,"nodeType":null,"messageId":"unusedVar","endLine":190,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'val' is defined but never used. Allowed unused args must match /^_/u.","line":266,"column":32,"nodeType":null,"messageId":"unusedVar","endLine":266,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'val' is defined but never used. Allowed unused args must match /^_/u.","line":342,"column":32,"nodeType":null,"messageId":"unusedVar","endLine":342,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'val' is defined but never used. Allowed unused args must match /^_/u.","line":449,"column":32,"nodeType":null,"messageId":"unusedVar","endLine":449,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'val' is defined but never used. Allowed unused args must match /^_/u.","line":551,"column":32,"nodeType":null,"messageId":"unusedVar","endLine":551,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\useSheetPaste.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\wav.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\__tests__\\workflowSheet.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\auth\\AuthApp.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\auth\\ErrorManagedApp.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":27,"column":5,"severity":1,"nodeType":null,"fix":{"range":[864,919],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import React, { useEffect } from 'react';\nimport { isElectron } from '../../api-variable';\nimport { logFile, LocalKey } from '../utils';\nimport ErrorBoundary from '../hoc/ErrorBoundary';\nimport App from '../App';\nimport { ErrorFallback } from '../components/ErrorFallback';\nimport Bugsnag from '@bugsnag/js';\nimport { API_CONFIG } from '../../api-variable';\nimport bugsnagClient from './bugsnagClient';\n\nconst prodOrQa = API_CONFIG.snagId !== '';\n\nconst SnagBoundary = prodOrQa\n ? Bugsnag.getPlugin('react')?.createErrorBoundary(React)\n : null;\n\nconst ErrorManagedApp: React.FC = () => {\n const [electronLog, setElectronLog] = React.useState('errorReporter');\n\n useEffect(() => {\n if (isElectron) {\n logFile().then((fullName: string) => {\n localStorage.setItem(LocalKey.errorLog, fullName);\n setElectronLog(fullName);\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return bugsnagClient && SnagBoundary ? (\n \n \n \n \n \n ) : (\n \n \n \n );\n};\n\nexport default ErrorManagedApp;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\auth\\Root.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\auth\\TokenChecked.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\auth\\bugsnagClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\BurritoBooks.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'getOrgDefault'. Either include it or remove the dependency array.","line":167,"column":6,"nodeType":"ArrayExpression","endLine":167,"endColumn":31,"suggestions":[{"desc":"Update the dependencies array to be: [teamId, teams, projects, getOrgDefault]","fix":{"range":[5829,5854],"text":"[teamId, teams, projects, getOrgDefault]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'bookSort', 'getProjectDefault', and 'num2BookCode'. Either include them or remove the dependency array.","line":202,"column":6,"nodeType":"ArrayExpression","endLine":202,"endColumn":53,"suggestions":[{"desc":"Update the dependencies array to be: [checked, plans, sections, passages, teamProjs, bookSort, getProjectDefault, num2BookCode]","fix":{"range":[7105,7152],"text":"[checked, plans, sections, passages, teamProjs, bookSort, getProjectDefault, num2BookCode]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'fetchBooks'. Either include it or remove the dependency array.","line":209,"column":6,"nodeType":"ArrayExpression","endLine":209,"endColumn":25,"suggestions":[{"desc":"Update the dependencies array to be: [lang, booksLoaded, fetchBooks]","fix":{"range":[7304,7323],"text":"[lang, booksLoaded, fetchBooks]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\BurritoContents.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'getOrgDefault'. Either include it or remove the dependency array.","line":41,"column":6,"nodeType":"ArrayExpression","endLine":41,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, teamId]","fix":{"range":[1455,1463],"text":"[getOrgDefault, teamId]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\BurritoFormat.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'getOrgDefault'. Either include it or remove the dependency array.","line":51,"column":6,"nodeType":"ArrayExpression","endLine":51,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, teamId]","fix":{"range":[1676,1684],"text":"[getOrgDefault, teamId]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\BurritoOption.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\BurritoStep.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\BurritoType.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\BurritoWrapper.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'getOrgDefault'. Either include it or remove the dependency array.","line":118,"column":6,"nodeType":"ArrayExpression","endLine":118,"endColumn":57,"suggestions":[{"desc":"Update the dependencies array to be: [teamId, teams, users, teamBibles, bibles, refresh, getOrgDefault]","fix":{"range":[4263,4314],"text":"[teamId, teams, users, teamBibles, bibles, refresh, getOrgDefault]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\MetaValue.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\MetadataView.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":2,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":2,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\MetadataView.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\VernacularAudioMissingTranscriptionDialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\akuoBookToUsfm.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\akuoBookToUsfm.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\burritoFormatParams.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\burritoUsfmChapters.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\burritoUsfmChapters.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\alignmentBuilder.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\alignmentBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\audioAlignment.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\audioAlignment2.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\audioBurrito.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\burritoBuilder.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\burritoBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\treeData.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\treeData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\types.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\wrapper.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\wrapperBuilder.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\data\\wrapperBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\jamesPublishingFixture.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\jamesSpeakerRightsFixture.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\normalizeTextToUsfm.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\normalizeTextToUsfm.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-explicit-any').","line":11,"column":3,"severity":1,"nodeType":null,"fix":{"range":[496,558],"text":" "}},{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-explicit-any').","line":67,"column":3,"severity":1,"nodeType":null,"fix":{"range":[2130,2192],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":2,"source":"import { DOMParser } from '@xmldom/xmldom';\nimport grammarWasmUrl from 'usfm-grammar-web/tree-sitter-usfm.wasm?url';\nimport parserWasmUrl from 'usfm-grammar-web/tree-sitter.wasm?url';\n\nexport type BurritoTextInputFormat = 'usfm' | 'usj' | 'usx';\n\ninterface USFMParserCtor {\n init(grammarPath?: string, parserPath?: string): Promise;\n // The published d.ts only declares `constructor(usfm: string)`, but we also\n // support `{ from_usj }` / `{ from_usx }` in runtime builds. Use `any`.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n new (usfm: string | null, usj?: any, usx?: Document | null): any;\n}\n\nlet parserCtorPromise: Promise | null = null;\nlet parserInitPromise: Promise | null = null;\n\nasync function getUSFMParserCtor(): Promise {\n if (parserCtorPromise == null) {\n parserCtorPromise = (async () => {\n const mod = (await import('usfm-grammar-web/dist/bundle.mjs')) as {\n USFMParser: USFMParserCtor;\n };\n return mod.USFMParser;\n })();\n }\n return await parserCtorPromise;\n}\n\nasync function ensureUSFMParserInitialized(USFMParser: USFMParserCtor) {\n if (parserInitPromise == null) {\n parserInitPromise = USFMParser.init(grammarWasmUrl, parserWasmUrl).catch(\n (err: unknown) => {\n // Allow subsequent calls to retry if initialization fails.\n parserInitPromise = null;\n throw err;\n }\n );\n }\n await parserInitPromise;\n}\n\nfunction normalizeNewlines(s: string): string {\n return String(s ?? '').replace(/\\r\\n?/g, '\\n');\n}\n\nexport async function normalizeTextToUsfm(\n input: string,\n format: BurritoTextInputFormat\n): Promise {\n const raw = normalizeNewlines(input);\n if (format === 'usfm') {\n return raw;\n }\n\n const USFMParser = await getUSFMParserCtor();\n await ensureUSFMParserInitialized(USFMParser);\n\n if (format === 'usj') {\n const usj = JSON.parse(raw);\n const parser = new USFMParser(null, usj);\n const usfm = String(parser?.usfm ?? '');\n return normalizeNewlines(usfm);\n }\n\n const usxDoc = new DOMParser().parseFromString(raw, 'application/xml');\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const parser = new USFMParser(null, null, usxDoc);\n const usfm = String(parser?.usfm ?? '');\n return normalizeNewlines(usfm);\n}\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\philippiansPublishingFixture.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\preprocessTextTranslationBurritoToUsfm.test.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":50,"column":7,"severity":1,"nodeType":null,"fix":{"range":[1712,1773],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { preprocessTextTranslationBurritoToUsfm } from './preprocessTextTranslationBurritoToUsfm';\n\njest.mock('./normalizeTextToUsfm', () => ({\n normalizeTextToUsfm: jest.fn(async (_input: string, format: string) => {\n return `\\\\id GEN\\n\\\\c 1\\n\\\\v 1 from-${format}`;\n }),\n}));\n\ndescribe('preprocessTextTranslationBurritoToUsfm', () => {\n it('adds text/usfm ingredient derived from usj/usx and writes metadata first', async () => {\n const files = new Map();\n const writes: Array<{ path: string; data: unknown }> = [];\n\n // `preprocessTextTranslationBurritoToUsfm` uses `path-browserify` which\n // emits POSIX separators, so keep fixture paths POSIX-like.\n const wrapperDir = '/wrapper';\n files.set(\n `${wrapperDir}/wrapper.json`,\n JSON.stringify({\n format: 'scripture burrito wrapper',\n meta: { name: { en: 'X' } },\n contents: { burritos: [{ path: 'text' }] },\n })\n );\n files.set(\n `${wrapperDir}/text/metadata.json`,\n JSON.stringify({\n type: { flavorType: { flavor: { name: 'textTranslation' } } },\n ingredients: {\n 'ingredients/GEN.usj': {\n mimeType: 'application/usj+json',\n scope: { GEN: ['1'] },\n },\n },\n })\n );\n files.set(\n `${wrapperDir}/text/ingredients/GEN.usj`,\n JSON.stringify({ type: 'USJ', version: '0.3.0', content: [] })\n );\n\n const ipc = {\n exists: async (p: string) => files.has(p),\n read: async (p: string) => files.get(p) ?? '',\n write: async (p: string, data: unknown) => {\n writes.push({ path: p, data });\n files.set(p, String(data));\n return undefined as any;\n },\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n md5File: async (_p: string) => 'md5',\n };\n\n await preprocessTextTranslationBurritoToUsfm(wrapperDir, ipc as any);\n\n const metaPath = `${wrapperDir}/text/metadata.json`;\n const updated = JSON.parse(files.get(metaPath) ?? '{}');\n const keys = Object.keys(updated.ingredients ?? {});\n\n // generated usfm should be present and appear first\n expect(keys[0]).toBe('ingredients/GEN.usfm');\n expect(updated.ingredients['ingredients/GEN.usfm'].mimeType).toBe(\n 'text/usfm'\n );\n expect(updated.ingredients['ingredients/GEN.usfm'].scope).toEqual({\n GEN: ['1'],\n });\n\n // file write for new usfm should exist\n expect(files.get(`${wrapperDir}/text/ingredients/GEN.usfm`)).toContain(\n '\\\\v 1 from-usj'\n );\n\n // and metadata should have been rewritten\n expect(writes.some((w) => w.path === metaPath)).toBe(true);\n });\n\n it('skips burritos and ingredients that resolve outside the wrapper directory', async () => {\n const readPaths: string[] = [];\n const writePaths: string[] = [];\n const wrapperDir = '/wrapper';\n\n const ipc = {\n exists: async () => true,\n read: async (p: string) => {\n readPaths.push(p);\n if (p.endsWith('wrapper.json')) {\n return JSON.stringify({\n format: 'scripture burrito wrapper',\n contents: {\n burritos: [\n { path: 'text' },\n { path: '../outside' },\n { path: 'evilmeta' },\n ],\n },\n });\n }\n if (p.includes('/text/') && p.endsWith('metadata.json')) {\n return JSON.stringify({\n type: { flavorType: { flavor: { name: 'textTranslation' } } },\n ingredients: {\n 'ingredients/GEN.usj': {\n mimeType: 'application/usj+json',\n scope: { GEN: ['1'] },\n },\n '../../escape/GEN.usj': {\n mimeType: 'application/usj+json',\n scope: { GEN: ['1'] },\n },\n },\n });\n }\n if (p.includes('/evilmeta/')) {\n return JSON.stringify({\n type: { flavorType: { flavor: { name: 'textTranslation' } } },\n ingredients: {},\n });\n }\n return '';\n },\n write: async (p: string) => {\n writePaths.push(p);\n },\n md5File: async () => 'md5',\n };\n\n const files = new Map([\n [`${wrapperDir}/text/ingredients/GEN.usj`, '{}'],\n ]);\n (ipc as any).exists = async (p: string) =>\n p.startsWith(`${wrapperDir}/`) &&\n (files.has(p) ||\n p.endsWith('metadata.json') ||\n p.endsWith('wrapper.json'));\n\n await preprocessTextTranslationBurritoToUsfm(wrapperDir, ipc as any);\n\n expect(readPaths.some((p) => p.includes('outside'))).toBe(false);\n expect(readPaths.every((p) => p.startsWith(`${wrapperDir}/`))).toBe(true);\n expect(writePaths.every((p) => p.startsWith(`${wrapperDir}/`))).toBe(true);\n expect(writePaths.some((p) => p.includes('escape'))).toBe(false);\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\preprocessTextTranslationBurritoToUsfm.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\resolveBurritoExportFolder.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\resolveBurritoExportFolder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useBurritoApmData.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":40,"column":31,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":40,"endColumn":69,"suppressions":[{"kind":"directive","justification":"resetModules + RTL pure + hook in one registry cycle"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":44,"column":7,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":44,"endColumn":57,"suppressions":[{"kind":"directive","justification":"resetModules + RTL pure + hook in one registry cycle"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":48,"column":34,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":48,"endColumn":71,"suppressions":[{"kind":"directive","justification":"resetModules + RTL pure + hook in one registry cycle"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":50,"column":33,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":50,"endColumn":63,"suppressions":[{"kind":"directive","justification":"resetModules + RTL pure + hook in one registry cycle"}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useBurritoApmData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useBurritoAudio.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":98,"column":31,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":98,"endColumn":69,"suppressions":[{"kind":"directive","justification":"resetModules + RTL pure + hook in one registry cycle"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":99,"column":30,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":99,"endColumn":63,"suppressions":[{"kind":"directive","justification":"resetModules + RTL pure + hook in one registry cycle"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":101,"column":31,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":101,"endColumn":59,"suppressions":[{"kind":"directive","justification":"resetModules + RTL pure + hook in one registry cycle"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":128,"column":31,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":128,"endColumn":69,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":129,"column":30,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":129,"endColumn":63,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":130,"column":28,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":130,"endColumn":58,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":143,"column":31,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":143,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":195,"column":31,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":195,"endColumn":69,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":196,"column":30,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":196,"endColumn":63,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":197,"column":28,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":197,"endColumn":58,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":210,"column":31,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":210,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":368,"column":30,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":368,"endColumn":60,"suppressions":[{"kind":"directive","justification":"resetModules pattern: re-require mocks from fresh module registry"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":453,"column":30,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":453,"endColumn":60,"suppressions":[{"kind":"directive","justification":"resetModules pattern"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":454,"column":33,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":454,"endColumn":67,"suppressions":[{"kind":"directive","justification":"resetModules pattern"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":455,"column":34,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":455,"endColumn":69,"suppressions":[{"kind":"directive","justification":"resetModules pattern"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":537,"column":30,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":537,"endColumn":60,"suppressions":[{"kind":"directive","justification":"resetModules pattern"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":672,"column":30,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":672,"endColumn":60,"suppressions":[{"kind":"directive","justification":"resetModules pattern"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":673,"column":33,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":673,"endColumn":67,"suppressions":[{"kind":"directive","justification":"resetModules pattern"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":674,"column":34,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":674,"endColumn":69,"suppressions":[{"kind":"directive","justification":"resetModules pattern"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":822,"column":30,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":822,"endColumn":60,"suppressions":[{"kind":"directive","justification":"resetModules pattern"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":823,"column":33,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":823,"endColumn":67,"suppressions":[{"kind":"directive","justification":"resetModules pattern"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":824,"column":34,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":824,"endColumn":69,"suppressions":[{"kind":"directive","justification":"resetModules pattern"}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":960,"column":30,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":960,"endColumn":60,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":961,"column":33,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":961,"endColumn":67,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":962,"column":34,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":962,"endColumn":69,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useBurritoAudio.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useBurritoIntellectualProperty.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useBurritoIntellectualProperty.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useBurritoNavigation.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useBurritoNavigation.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useBurritoText.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useBurritoText.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useCreateBurrito.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":225,"column":40,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":225,"endColumn":62,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":229,"column":25,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":229,"endColumn":56,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":236,"column":30,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":236,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":241,"column":31,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":241,"endColumn":66,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":253,"column":34,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":253,"endColumn":71,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":263,"column":28,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":263,"endColumn":58,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":267,"column":31,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":267,"endColumn":69,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":268,"column":32,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":268,"endColumn":61,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":363,"column":32,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":363,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":562,"column":32,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":562,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":642,"column":32,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":642,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":658,"column":9,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":658,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":710,"column":9,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":710,"endColumn":52,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":824,"column":38,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":824,"endColumn":71,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":868,"column":38,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":868,"endColumn":71,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\useCreateBurrito.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'fetchBooks'. Either include it or remove the dependency array.","line":119,"column":6,"nodeType":"ArrayExpression","endLine":119,"endColumn":25,"suggestions":[{"desc":"Update the dependencies array to be: [lang, booksLoaded, fetchBooks]","fix":{"range":[4622,4641],"text":"[lang, booksLoaded, fetchBooks]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has a missing dependency: 'getOrgDefault'. Either include it or remove the dependency array.","line":132,"column":5,"nodeType":"ArrayExpression","endLine":132,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, teamId]","fix":{"range":[5093,5101],"text":"[getOrgDefault, teamId]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\usfmTextConvert.test.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":2,"column":1,"severity":1,"nodeType":null,"fix":{"range":[58,112],"text":" "}}],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-empty-function","severity":2,"message":"Unexpected empty constructor.","line":34,"column":34,"nodeType":"FunctionExpression","messageId":"unexpected","endLine":34,"endColumn":36,"suggestions":[{"messageId":"suggestComment","data":{"name":"constructor"},"fix":{"range":[900,900],"text":" /* empty */ "},"desc":"Add comment inside empty constructor."}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable @typescript-eslint/no-empty-function */\n/* eslint-disable @typescript-eslint/no-unused-vars */\njest.mock('@xmldom/xmldom', () => ({\n XMLSerializer: class XMLSerializer {\n serializeToString() {\n return '';\n }\n },\n}));\n\njest.mock('usfm-grammar-web/tree-sitter-usfm.wasm?url', () => 'grammar.wasm', {\n virtual: true,\n});\njest.mock('usfm-grammar-web/tree-sitter.wasm?url', () => 'parser.wasm', {\n virtual: true,\n});\n\ndescribe('convertBurritoText', () => {\n beforeEach(() => {\n jest.resetModules();\n jest.clearAllMocks();\n });\n\n function mockParser(modImpl: {\n init?: jest.Mock;\n errors?: unknown;\n toUSJ?: unknown;\n toUSX?: unknown;\n }) {\n const init = modImpl.init ?? jest.fn().mockResolvedValue(undefined);\n const USFMParser = class {\n static init = init;\n errors = modImpl.errors ?? null;\n constructor(_usfm: string) {}\n toUSJ() {\n return modImpl.toUSJ ?? { ok: true };\n }\n toUSX() {\n return (\n modImpl.toUSX ?? {\n nodeType: 1,\n nodeName: 'usx',\n childNodes: [],\n attributes: [],\n }\n );\n }\n };\n\n jest.doMock('usfm-grammar-web/dist/bundle.mjs', () => ({ USFMParser }), {\n virtual: true,\n });\n\n return { init };\n }\n\n it('converts to USJ (JSON pretty printed) after init', async () => {\n const { init } = mockParser({\n toUSJ: { book: 'GEN', chapters: [1] },\n errors: null,\n });\n\n const { convertBurritoText } = await import('./usfmTextConvert');\n const out = await convertBurritoText('\\\\id GEN', 'usj');\n\n expect(init).toHaveBeenCalledWith('grammar.wasm', 'parser.wasm');\n expect(out).toContain('\"book\": \"GEN\"');\n expect(out).toContain('\\n '); // pretty-print indentation\n });\n\n it('converts to USX (XML string) after init', async () => {\n const { init } = mockParser({\n toUSX: { nodeType: 1, nodeName: 'usx', childNodes: [], attributes: [] },\n errors: null,\n });\n\n const { convertBurritoText } = await import('./usfmTextConvert');\n const out = await convertBurritoText('\\\\id GEN', 'usx');\n\n expect(init).toHaveBeenCalledWith('grammar.wasm', 'parser.wasm');\n expect(typeof out).toBe('string');\n expect(out.toLowerCase()).toContain('usx');\n });\n\n it('throws when parser reports errors array', async () => {\n mockParser({\n errors: [{ message: 'bad usfm' }],\n });\n\n const { convertBurritoText } = await import('./usfmTextConvert');\n await expect(convertBurritoText('bad', 'usj')).rejects.toThrow(\n /USFM parse errors/\n );\n });\n\n it('caches init across calls within module (init called once)', async () => {\n const { init } = mockParser({\n errors: null,\n toUSJ: { ok: 1 },\n });\n\n const { convertBurritoText } = await import('./usfmTextConvert');\n await convertBurritoText('\\\\id GEN', 'usj');\n await convertBurritoText('\\\\id GEN', 'usj');\n\n expect(init).toHaveBeenCalledTimes(1);\n });\n\n it('allows retry after init failure (second call re-inits)', async () => {\n const init = jest\n .fn()\n .mockRejectedValueOnce(new Error('init failed'))\n .mockResolvedValueOnce(undefined);\n mockParser({ init, errors: null, toUSJ: { ok: true } });\n\n const { convertBurritoText } = await import('./usfmTextConvert');\n\n await expect(convertBurritoText('\\\\id GEN', 'usj')).rejects.toThrow(\n /init failed/\n );\n await expect(convertBurritoText('\\\\id GEN', 'usj')).resolves.toContain(\n '\"ok\": true'\n );\n expect(init).toHaveBeenCalledTimes(2);\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\usfmTextConvert.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\vernacularAudioWarnings.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\burrito\\vernacularAudioWarnings.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\AeroTaskErrorMessage.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\AsrAlphabet.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'scriptName', 'setState', and 'state.method'. Either include them or remove the dependency array. If 'setState' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":42,"column":6,"nodeType":"ArrayExpression","endLine":42,"endColumn":30,"suggestions":[{"desc":"Update the dependencies array to be: [scriptName, setState, state?.language?.bcp47, state.method]","fix":{"range":[1687,1711],"text":"[scriptName, setState, state?.language?.bcp47, state.method]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\AsrProgress.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'closing' and 'launchTimer'. Either include them or remove the dependency array.","line":337,"column":6,"nodeType":"ArrayExpression","endLine":337,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [closing, launchTimer, taskId]","fix":{"range":[10352,10360],"text":"[closing, launchTimer, taskId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'closing', 'force', 'mediaId', 'memory', 'postTranscribe', 'status', and 't.transcriptionExists'. Either include them or remove the dependency array.","line":366,"column":6,"nodeType":"ArrayExpression","endLine":366,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [closing, force, mediaId, memory, postTranscribe, status, t.transcriptionExists]","fix":{"range":[11148,11150],"text":"[closing, force, mediaId, memory, postTranscribe, status, t.transcriptionExists]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\AsrSettings.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\AsrTarget.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\SelectAsrLanguage.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'fetchRecommendations', 'getAsrSettings', 'getCachedSisterRecommendations', 'getVernacularLanguage', 'saveSisterRecommendations', and 'seedSuggestions'. Either include them or remove the dependency array.","line":116,"column":6,"nodeType":"ArrayExpression","endLine":116,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [fetchRecommendations, getAsrSettings, getCachedSisterRecommendations, getVernacularLanguage, saveSisterRecommendations, seedSuggestions]","fix":{"range":[3844,3846],"text":"[fetchRecommendations, getAsrSettings, getCachedSisterRecommendations, getVernacularLanguage, saveSisterRecommendations, seedSuggestions]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\aeroTaskError.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\aeroTaskError.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\aeroTranscriptionPoll.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\aeroTranscriptionPoll.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\asrLanguages.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\asrScriptDetail.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\asrState.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\asrState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\useRecommendAsrLanguage.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\asr\\useRecommendAsrLanguage.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\PassageInfo.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\crossChapterRefs.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\crossChapterRefs.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\doChapter.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\doChapter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\getLastVerse.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\getLastVerse.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\getLocalParatextText.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\getLocalParatextText.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\localSync.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\localSync.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\paratextPaths.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\paratextPaths.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\parseTranscription.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\parseTranscription.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\postPass.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\postPass.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\readChapter.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\readChapter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\usxNodeChange.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\usxNodeChange.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\usxNodeContent.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\usxNodeContent.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":18,"column":5,"severity":1,"nodeType":null,"fix":{"range":[421,485],"text":" "}}],"suppressedMessages":[{"ruleId":"prefer-const","severity":2,"message":"'vend' is never reassigned. Use 'const' instead.","line":75,"column":18,"nodeType":"Identifier","messageId":"useConst","endLine":75,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import xpath from 'xpath';\nimport {\n isAfterSection,\n isPara,\n isSection,\n isText,\n isVerse,\n} from './usxNodeType';\nimport { Passage } from '../../model';\nimport { vInt } from './vInt';\n\nconst vrefRe = /^([0-9]+[a-f]?)[^0-9]?([0-9]+[a-f]?)?$/;\n\nexport const domVnum = (v: Element) => {\n const vrefAttr = v.getAttribute('number');\n const vrefMatch = vrefAttr ? vrefRe.exec(vrefAttr) : null;\n if (vrefMatch) {\n /* eslint-disable-next-line @typescript-eslint/no-unused-vars */\n const [_, vstart, vend] = vrefMatch;\n return [vInt(vstart), vInt(vend) || vInt(vstart)];\n }\n return [];\n};\n\nexport const firstVerse = (para: Node) => {\n let verse = para.firstChild;\n while (verse && !isVerse(verse)) verse = verse?.nextSibling;\n return verse as Element;\n};\n\nexport const bruteForceVerses = (node: Node | null, verses: Element[]) => {\n for (let n = node; n !== null; n = n.nextSibling) {\n if (isVerse(n)) {\n verses.push(n as Element);\n }\n bruteForceVerses(n.firstChild, verses);\n }\n};\n\nexport const getVerses = (node: Node) => {\n try {\n if (isPara(node)) {\n const verses: Element[] = [];\n for (\n let n: Node | null = node.firstChild;\n n !== null;\n n = n.nextSibling\n ) {\n if (isVerse(n)) {\n verses.push(n as Element);\n }\n }\n return verses;\n } else return xpath.select('//verse', node) as Element[];\n } catch {\n //let sDebug = xmlSerializer.serializeToString(node);\n const verses: Element[] = [];\n bruteForceVerses(node, verses);\n return verses;\n }\n};\n\nexport const getExistingVerses = (\n doc: Document,\n p: Passage,\n includeExact: boolean = false\n) => {\n const verses = getVerses(doc.documentElement);\n const allVerses = Array();\n const first = p?.attributes.startVerse || 0;\n const last = p?.attributes.endVerse || 0;\n let exactVerse: Element | undefined;\n verses.forEach((v) => {\n // eslint-disable-next-line prefer-const\n let [vstart, vend] = domVnum(v);\n if (vstart) {\n if (vstart === first && vend === last) {\n exactVerse = v;\n if (!includeExact) {\n vstart = 0;\n if (p.attributes.sequencenum === 1 && isAfterSection(v))\n allVerses.push(isAfterSection(v) as Element);\n }\n }\n if (vstart >= first && vend <= last && !allVerses.includes(v)) {\n allVerses.push(v);\n if (p.attributes.sequencenum === 1 && isAfterSection(v))\n allVerses.push(isAfterSection(v) as Element);\n }\n }\n });\n return { allVerses, exactVerse };\n};\n\nexport const getPassageVerses = (doc: Document, p: Passage) => {\n const existing = getExistingVerses(doc, p, true);\n if (existing.allVerses.length === 0) throw new Error('no range');\n let transcription = '';\n existing.allVerses.forEach((v) => {\n if (isVerse(v))\n transcription +=\n '\\\\v ' +\n v.getAttribute('number') +\n ' ' +\n verseText(v).replace('\\\\p', '\\r');\n });\n return transcription;\n};\n\nexport const logUsxStructure = (doc: Document, label?: string) => {\n const root = doc.documentElement;\n const lines: string[] = [];\n for (let i = 0; i < root.childNodes.length; i++) {\n const node = root.childNodes[i];\n if (isPara(node)) {\n const el = node as Element;\n const style = el.getAttribute('style') || '?';\n let content = '';\n for (let j = 0; j < el.childNodes.length; j++) {\n const child = el.childNodes[j];\n if (isVerse(child))\n content += `\\\\v ${(child as Element).getAttribute('number') || '?'} `;\n else if (isSection(child)) content += `[s] `;\n else if (isText(child)) {\n const txt = (child.nodeValue || '').replace(/[\\r\\n]/g, '');\n if (txt) content += txt;\n }\n }\n lines.push(`\\\\${style} ${content}`.trimEnd());\n } else if (isText(node)) {\n const txt = (node.nodeValue || '').trim();\n if (txt) lines.push(txt);\n }\n }\n console.log(`--- ${label ?? 'USX'} ---\\n` + lines.join('\\n'));\n};\n\nexport const verseText = (v: Element) => {\n let next: Node | undefined | null =\n v.firstChild || v.nextSibling || v.parentNode?.nextSibling;\n let text = '';\n while (next) {\n if (isSection(next) || isVerse(next)) next = null;\n else if (isText(next)) {\n text += next.nodeValue;\n }\n if (next)\n next =\n next.firstChild || next.nextSibling || next.parentNode?.nextSibling;\n }\n return text;\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\usxNodeType.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\usxNodeType.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\vInt.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\localParatext\\writeChapter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\player\\usePlayerLogic.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'mediafileRef'. Either include it or remove the dependency array.","line":71,"column":6,"nodeType":"ArrayExpression","endLine":71,"endColumn":23,"suggestions":[{"desc":"Update the dependencies array to be: [mediafileRef, playerMediafile]","fix":{"range":[2123,2140],"text":"[mediafileRef, playerMediafile]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'onSegment', 'segmentsRef', 'setDefaultSegments', and 'setSegmentToWhole'. Either include them or remove the dependency array.","line":81,"column":6,"nodeType":"ArrayExpression","endLine":81,"endColumn":39,"suggestions":[{"desc":"Update the dependencies array to be: [allowSegment, onSegment, segmentsRef, setDefaultSegments, setSegmentToWhole, suggestedSegments]","fix":{"range":[2518,2551],"text":"[allowSegment, onSegment, segmentsRef, setDefaultSegments, setSegmentToWhole, suggestedSegments]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'loadSegments' and 'setDefaultSegments'. Either include them or remove the dependency array.","line":87,"column":6,"nodeType":"ArrayExpression","endLine":87,"endColumn":37,"suggestions":[{"desc":"Update the dependencies array to be: [allowSegment, loadSegments, playerMediafile, setDefaultSegments]","fix":{"range":[2713,2744],"text":"[allowSegment, loadSegments, playerMediafile, setDefaultSegments]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'playingRef' and 'setRequestPlay'. Either include them or remove the dependency array.","line":166,"column":6,"nodeType":"ArrayExpression","endLine":166,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [playing, playingRef, setRequestPlay]","fix":{"range":[5165,5174],"text":"[playing, playingRef, setRequestPlay]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setInitialPosition'. Either include it or remove the dependency array.","line":171,"column":6,"nodeType":"ArrayExpression","endLine":171,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [position, setInitialPosition]","fix":{"range":[5297,5307],"text":"[position, setInitialPosition]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\voice\\PersonalizeVoicePermission.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'state?.fullName'. Either include it or remove the dependency array.","line":212,"column":6,"nodeType":"ArrayExpression","endLine":212,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [state?.fullName]","fix":{"range":[6326,6328],"text":"[state?.fullName]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'excludeOptions', 'genderMsg', 'handleChangeAge', 'handleChangeGender', 'handleExcludeChange', 'handleFilter', 'handleLanguageChange', 't.age', 't.allTeams', 't.excludedLanguages', and 't.gender'. Either include them or remove the dependency array. You can also replace multiple useState variables with useReducer if 'setDecorations' needs the current value of 'genderMsg'.","line":284,"column":6,"nodeType":"ArrayExpression","endLine":284,"endColumn":46,"suggestions":[{"desc":"Update the dependencies array to be: [curState, minorMsg, language, hideLang, t.allTeams, t.gender, t.age, t.excludedLanguages, handleChangeGender, genderMsg, handleChangeAge, handleFilter, handleLanguageChange, excludeOptions, handleExcludeChange]","fix":{"range":[8431,8471],"text":"[curState, minorMsg, language, hideLang, t.allTeams, t.gender, t.age, t.excludedLanguages, handleChangeGender, genderMsg, handleChangeAge, handleFilter, handleLanguageChange, excludeOptions, handleExcludeChange]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\voice\\SelectSponsor.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'getOrgDefault'. Either include it or remove the dependency array.","line":32,"column":6,"nodeType":"ArrayExpression","endLine":32,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, team]","fix":{"range":[1274,1280],"text":"[getOrgDefault, team]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\voice\\SelectVoice.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'getOrgDefault'. Either include it or remove the dependency array.","line":55,"column":6,"nodeType":"ArrayExpression","endLine":55,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault]","fix":{"range":[1703,1705],"text":"[getOrgDefault]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has missing dependencies: 'ipRecs' and 'memory'. Either include them or remove the dependency array.","line":75,"column":6,"nodeType":"ArrayExpression","endLine":75,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [ipRecs, voice, org, memory]","fix":{"range":[2267,2279],"text":"[ipRecs, voice, org, memory]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\voice\\VoiceStatement.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'handleCopy' and 'handlePersonalize'. Either include them or remove the dependency array.","line":70,"column":6,"nodeType":"ArrayExpression","endLine":70,"endColumn":60,"suggestions":[{"desc":"Update the dependencies array to be: [registerActions, permStatement, state, voice, saving, handleCopy, handlePersonalize]","fix":{"range":[2131,2185],"text":"[registerActions, permStatement, state, voice, saving, handleCopy, handlePersonalize]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setStatement'. Either include it or remove the dependency array. If 'setStatement' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":75,"column":6,"nodeType":"ArrayExpression","endLine":75,"endColumn":21,"suggestions":[{"desc":"Update the dependencies array to be: [permStatement, setStatement]","fix":{"range":[2323,2338],"text":"[permStatement, setStatement]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\voice\\useVoicePermission.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 't.aiipStatement', 't.ipStatement', 't.myProjects', 't.stAge', 't.stCategories', 't.stGender', 't.stHired', 't.stJoin', 't.stLangClause', 't.stMyLang', 't.stMyLangs', 't.stNotGiven', 't.stNotIdentified', 't.stTeam', 't.stTeamClause', 't.stThisTeam', and 't.stVolunteer'. Either include them or remove the dependency array.","line":87,"column":6,"nodeType":"ArrayExpression","endLine":87,"endColumn":29,"suggestions":[{"desc":"Update the dependencies array to be: [permState, team, aiip, t.myProjects, t.stTeam, t.stThisTeam, t.stGender, t.stNotGiven, t.stAge, t.stCategories, t.stJoin, t.stLangClause, t.stMyLangs, t.stMyLang, t.stTeamClause, t.stHired, t.stVolunteer, t.aiipStatement, t.stNotIdentified, t.ipStatement]","fix":{"range":[2914,2937],"text":"[permState, team, aiip, t.myProjects, t.stTeam, t.stThisTeam, t.stGender, t.stNotGiven, t.stAge, t.stCategories, t.stJoin, t.stLangClause, t.stMyLangs, t.stMyLang, t.stTeamClause, t.stHired, t.stVolunteer, t.aiipStatement, t.stNotIdentified, t.ipStatement]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\business\\voice\\voicePermOpts.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AboutDialog.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'no-template-curly-in-string').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,48],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable no-template-curly-in-string */\nimport { IMainStrings, ISharedStrings } from '../model';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Accordion,\n AccordionSummary,\n AccordionDetails,\n List,\n ListItem,\n ListItemText,\n Link,\n Tooltip,\n Box,\n BoxProps,\n} from '@mui/material';\nimport Typography, { TypographyProps } from '@mui/material/Typography';\nimport { styled } from '@mui/material/styles';\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\nimport { API_CONFIG } from '../../api-variable';\nimport about from '../assets/about.json';\nimport stringReplace from 'react-string-replace';\nimport { useSnackBar } from '../hoc/SnackBar';\nimport { ApmLogo } from '../control/ApmLogo';\nimport { Button, StyledHeading } from '../control';\nimport { mainSelector, sharedSelector } from '../selector';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport packageJson from '../../package.json';\nimport buildDateJson from '../buildDate.json';\nconst version = packageJson.version;\nconst copyright = packageJson.build.copyright;\nconst author = packageJson.author.name;\nconst buildDate = buildDateJson.date;\n\nconst CopyrightText = styled(Typography)(() => ({\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n}));\n\nconst ProductIdentBox = styled(Box)(() => ({\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n}));\n\nconst Paragraphs = styled(Box)(() => ({\n display: 'flex',\n flexDirection: 'column',\n}));\n\nconst VersionDiv = styled('div')(({ theme }) => ({\n paddingTop: theme.spacing(2),\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n}));\n\ninterface ItemsProps {\n items: string[];\n kid: string;\n}\nconst ListItems = ({ items, kid }: ItemsProps) => {\n const part = (s: string, i: number) => s.split('|')[i];\n\n return (\n \n {items.map((i, n) => (\n \n \n {stringReplace(part(i, 0), part(i, 1), (m: string) => (\n \n {m}\n \n ))}\n \n \n ))}\n \n );\n};\n\nconst ParaItems = ({ items, kid }: ItemsProps) => {\n return (\n \n {items.map((i, n) => (\n \n {i}\n \n ))}\n \n );\n};\n\ninterface LicenseProps {\n title: string;\n url: string;\n text: string[];\n product: string[];\n kid: string;\n}\n\nconst LicenseAccordion = ({ title, url, text, product, kid }: LicenseProps) => {\n return (\n <>\n \n }\n aria-controls=\"panel1-content\"\n id=\"panel1-header\"\n >\n \n {\n \n {title}\n \n }\n \n \n \n \n \n \n \n \n );\n};\n\ninterface AboutDialogProps {\n open: boolean;\n onClose: () => void;\n}\n\nfunction AboutDialog(props: AboutDialogProps) {\n const { onClose, open } = props;\n const t: IMainStrings = useSelector(mainSelector, shallowEqual);\n const ts: ISharedStrings = useSelector(sharedSelector, shallowEqual);\n const { showMessage } = useSnackBar();\n\n const handleClose = () => onClose();\n const handleExit = () => onClose();\n\n const handleVersionCopy = () => {\n navigator.clipboard\n .writeText(`${API_CONFIG.productName} ${version} - ${buildDate}`)\n .catch(() => {\n showMessage(ts.cantCopy);\n });\n };\n\n return (\n \n {t.about}\n \n \n
\n \n \n {'\\u00A0'}\n {API_CONFIG.productName}\n \n \n {t.version.replace('{0}', version).replace('{1}', buildDate)}\n \n \n {copyright.replace('${author}', author)}\n \n
\n
\n {t.team}\n \n {t.thanks}\n \n \n {t.reliesOn.replace('{0}', API_CONFIG.productName)}\n \n \n \n \n \n \n \n
\n \n \n \n \n );\n}\nexport default AboutDialog;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AlertDialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AllDone.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AltActionBar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ApmSplash.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\App\\AppHead.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'anySaving'. Either include it or remove the dependency array.","line":105,"column":45,"nodeType":"ArrayExpression","endLine":105,"endColumn":59,"suggestions":[{"desc":"Update the dependencies array to be: [anySaving]","fix":{"range":[4192,4206],"text":"[anySaving]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has an unnecessary dependency: 'pathname'. Either exclude it or remove the dependency array.","line":125,"column":6,"nodeType":"ArrayExpression","endLine":125,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: []","fix":{"range":[4929,4939],"text":"[]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getGlobal' and 'handleMenu'. Either include them or remove the dependency array.","line":273,"column":6,"nodeType":"ArrayExpression","endLine":273,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [getGlobal, handleMenu, tokenState]","fix":{"range":[9864,9876],"text":"[getGlobal, handleMenu, tokenState]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'handleUnload', 'pathname', and 'user'. Either include them or remove the dependency array.","line":287,"column":6,"nodeType":"ArrayExpression","endLine":287,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [handleUnload, pathname, user]","fix":{"range":[10277,10279],"text":"[handleUnload, pathname, user]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'downDone', 'isMounted', 'isOffline', and 'startSave'. Either include them or remove the dependency array.","line":299,"column":6,"nodeType":"ArrayExpression","endLine":299,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [downDone, exitAlert, isChanged, isMounted, isOffline, startSave]","fix":{"range":[10606,10628],"text":"[downDone, exitAlert, isChanged, isMounted, isOffline, startSave]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'onDownloadAlert'. Either include it or remove the dependency array. If 'onDownloadAlert' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":305,"column":6,"nodeType":"ArrayExpression","endLine":305,"endColumn":21,"suggestions":[{"desc":"Update the dependencies array to be: [downloadAlert, onDownloadAlert]","fix":{"range":[10798,10813],"text":"[downloadAlert, onDownloadAlert]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'errorReporter'. Either include it or remove the dependency array.","line":311,"column":6,"nodeType":"ArrayExpression","endLine":311,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [errorReporter, pathname]","fix":{"range":[10996,11006],"text":"[errorReporter, pathname]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'showMessage'. Either include it or remove the dependency array.","line":318,"column":6,"nodeType":"ArrayExpression","endLine":318,"endColumn":34,"suggestions":[{"desc":"Update the dependencies array to be: [orbitStatus, orbitErrorMsg, showMessage]","fix":{"range":[11158,11186],"text":"[orbitStatus, orbitErrorMsg, showMessage]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\App\\AppLayout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\App\\ContentLayout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\App\\DetailTitle.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\App\\HeadStatus.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'hasOfflineProjects'. Either include it or remove the dependency array.","line":104,"column":6,"nodeType":"ArrayExpression","endLine":104,"endColumn":23,"suggestions":[{"desc":"Update the dependencies array to be: [hasOfflineProjects, offlineProjects]","fix":{"range":[4967,4984],"text":"[hasOfflineProjects, offlineProjects]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'errorReporter', 'latestVersion', 'setLatestRelease', 'setLatestVersion', 'showMessage', and 't.updateAvailable'. Either include them or remove the dependency array.","line":202,"column":6,"nodeType":"ArrayExpression","endLine":202,"endColumn":30,"suggestions":[{"desc":"Update the dependencies array to be: [updates, version, lang, latestVersion, setLatestVersion, setLatestRelease, showMessage, t.updateAvailable, errorReporter]","fix":{"range":[7973,7997],"text":"[updates, version, lang, latestVersion, setLatestVersion, setLatestRelease, showMessage, t.updateAvailable, errorReporter]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\App\\OrgHead.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has an unnecessary dependency: 'user'. Either exclude it or remove the dependency array.","line":78,"column":5,"nodeType":"ArrayExpression","endLine":78,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: []","fix":{"range":[3477,3483],"text":"[]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ArtifactStatus.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'curVersionCount', 'segProgress', 'segsComp', and 'uniqueSegs'. Either include them or remove the dependency array.","line":88,"column":6,"nodeType":"ArrayExpression","endLine":96,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [rowData, recordType, currentVersion, segments, vernacularMediaId, languageBcp47, recordTypeId, curVersionCount, uniqueSegs, segsComp, segProgress]","fix":{"range":[3054,3182],"text":"[rowData, recordType, currentVersion, segments, vernacularMediaId, languageBcp47, recordTypeId, curVersionCount, uniqueSegs, segsComp, segProgress]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AssignSection.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getOrganizedBy' and 'organizedBy'. Either include them or remove the dependency array.","line":440,"column":6,"nodeType":"ArrayExpression","endLine":440,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [getOrganizedBy, organizedBy]","fix":{"range":[12720,12722],"text":"[getOrganizedBy, organizedBy]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AssignmentTable.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'getNameCell', 'getSchemeName', 'passagesCol', 'sortCol', 'ts.scheme', and 'ts.scheme2'. Either include them or remove the dependency array.","line":256,"column":5,"nodeType":"ArrayExpression","endLine":264,"endColumn":6,"suggestions":[{"desc":"Update the dependencies array to be: [flat, organizedBy, addWidth, getNameCell, passagesCol, isPermission, ts.scheme, ts.scheme2, getSchemeName, sortCol]","fix":{"range":[7546,7673],"text":"[flat, organizedBy, addWidth, getNameCell, passagesCol, isPermission, ts.scheme, ts.scheme2, getSchemeName, sortCol]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setDimensions'. Either include it or remove the dependency array.","line":293,"column":6,"nodeType":"ArrayExpression","endLine":293,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [setDimensions, totalWidth]","fix":{"range":[8465,8477],"text":"[setDimensions, totalWidth]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setDimensions'. Either include it or remove the dependency array.","line":307,"column":6,"nodeType":"ArrayExpression","endLine":307,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [setDimensions]","fix":{"range":[8831,8833],"text":"[setDimensions]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'check', 'getAssignments', and 'selectedRows.ids.size'. Either include them or remove the dependency array.","line":486,"column":6,"nodeType":"ArrayExpression","endLine":498,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [plan, passages, mediafiles, sections, users, roles, activityState, allBookData, refresh, openSections, schemes, getAssignments, selectedRows.ids.size, check]","fix":{"range":[14178,14339],"text":"[plan, passages, mediafiles, sections, users, roles, activityState, allBookData, refresh, openSections, schemes, getAssignments, selectedRows.ids.size, check]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioDownload.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioExportMenu.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioProgressButton.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'doToggle' and 'toggle'. Either include them or remove the dependency array.","line":95,"column":6,"nodeType":"ArrayExpression","endLine":95,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [doToggle, toggle]","fix":{"range":[2747,2749],"text":"[doToggle, toggle]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\AudioTab.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setUrlOpen'. Either include it or remove the dependency array.","line":218,"column":6,"nodeType":"ArrayExpression","endLine":218,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [setUrlOpen, urlOpen]","fix":{"range":[7493,7502],"text":"[setUrlOpen, urlOpen]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'allBookData', 'data', 'passages', 'planMedia', 'planRec?.attributes?.name', 'sectionMap', and 'sections'. Either include them or remove the dependency array. You can also replace multiple useState variables with useReducer if 'setData' needs the current value of 'planMedia'.","line":247,"column":6,"nodeType":"ArrayExpression","endLine":247,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [allBookData, data, passages, planMedia, planRec?.attributes?.name, playItem, sectionMap, sections]","fix":{"range":[8247,8257],"text":"[allBookData, data, passages, planMedia, planRec?.attributes?.name, playItem, sectionMap, sections]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'allBookData', 'planRec?.attributes?.name', 'playItem', and 'sectionMap'. Either include them or remove the dependency array.","line":260,"column":6,"nodeType":"ArrayExpression","endLine":260,"endColumn":46,"suggestions":[{"desc":"Update the dependencies array to be: [planMedia, passages, sections, refresh, planRec?.attributes?.name, playItem, allBookData, sectionMap]","fix":{"range":[8561,8601],"text":"[planMedia, passages, sections, refresh, planRec?.attributes?.name, playItem, allBookData, sectionMap]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'allBookData' and 'plan'. Either include them or remove the dependency array.","line":268,"column":6,"nodeType":"ArrayExpression","endLine":268,"endColumn":63,"suggestions":[{"desc":"Update the dependencies array to be: [planMedia, passages, sections, attachVisible, autoMatch, allBookData, plan]","fix":{"range":[8871,8928],"text":"[planMedia, passages, sections, attachVisible, autoMatch, allBookData, plan]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'hasPassage' and 'pdata'. Either include them or remove the dependency array.","line":286,"column":6,"nodeType":"ArrayExpression","endLine":286,"endColumn":43,"suggestions":[{"desc":"Update the dependencies array to be: [attachMap, attachVisible, autoMatch, hasPassage, pdata]","fix":{"range":[9412,9449],"text":"[attachMap, attachVisible, autoMatch, hasPassage, pdata]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'handleSave', 'showMessage', 't.matchAdded', and 't.noMatch'. Either include them or remove the dependency array.","line":324,"column":5,"nodeType":"ArrayExpression","endLine":324,"endColumn":31,"suggestions":[{"desc":"Update the dependencies array to be: [pdata.length, data.length, allBookData, showMessage, t.noMatch, t.matchAdded, handleSave]","fix":{"range":[10596,10622],"text":"[pdata.length, data.length, allBookData, showMessage, t.noMatch, t.matchAdded, handleSave]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\AudioTable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\DetachCell.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\GetReference.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\IAttachMap.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\IPRow.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\IRow.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\PassageChooser.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setDimensions'. Either include it or remove the dependency array.","line":82,"column":6,"nodeType":"ArrayExpression","endLine":82,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [setDimensions, totalWidth]","fix":{"range":[2596,2608],"text":"[setDimensions, totalWidth]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setDimensions'. Either include it or remove the dependency array.","line":96,"column":6,"nodeType":"ArrayExpression","endLine":96,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [setDimensions]","fix":{"range":[2962,2964],"text":"[setDimensions]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\PlayCell.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\SelectLatest.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\Template.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'template'. Either include it or remove the dependency array.","line":39,"column":6,"nodeType":"ArrayExpression","endLine":39,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [template]","fix":{"range":[1216,1218],"text":"[template]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\VersionDlg.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'versionSortModel'. Either include it or remove the dependency array.","line":53,"column":5,"nodeType":"ArrayExpression","endLine":53,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [data, versionSortModel]","fix":{"range":[1968,1974],"text":"[data, versionSortModel]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\getMedia.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\getMedia.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\getPassages.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\getPassages.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\getSection.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\isAttached.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\makeRefMap.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\pad.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\usePassageVersionAudioRows.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\AudioTab\\usePassageVersionAudioRows.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getProjectDefault' and 'memory'. Either include them or remove the dependency array.","line":84,"column":6,"nodeType":"ArrayExpression","endLine":84,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [getProjectDefault, memory, project]","fix":{"range":[2850,2859],"text":"[getProjectDefault, memory, project]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'IsVernacularMedia', 'allBookData', and 'data'. Either include them or remove the dependency array.","line":104,"column":6,"nodeType":"ArrayExpression","endLine":113,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [mediaFiles, sections, passages, planRec, passId, playItem, refresh, sectionMap, data, allBookData, IsVernacularMedia]","fix":{"range":[3464,3581],"text":"[mediaFiles, sections, passages, planRec, passId, playItem, refresh, sectionMap, data, allBookData, IsVernacularMedia]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\BookSelect.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\BurritoHeader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\BurritoUpload.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Busy.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ConfirmPublishDialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ContextHelp.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'reset'. Either include it or remove the dependency array. If 'reset' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":60,"column":6,"nodeType":"ArrayExpression","endLine":60,"endColumn":36,"suggestions":[{"desc":"Update the dependencies array to be: [helpToggle, isOffline, reset, topic]","fix":{"range":[2108,2138],"text":"[helpToggle, isOffline, reset, topic]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\DeleteExpansion.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\CategoryList.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'discussionOrg', 'onCatFilter', and 't.uncategorized'. Either include them or remove the dependency array.","line":81,"column":6,"nodeType":"ArrayExpression","endLine":81,"endColumn":51,"suggestions":[{"desc":"Update the dependencies array to be: [discussions, artifactCategory, organization, onCatFilter, discussionOrg, t.uncategorized]","fix":{"range":[2488,2533],"text":"[discussions, artifactCategory, organization, onCatFilter, discussionOrg, t.uncategorized]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\CommentCard.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearRequested', 'comment.id', 'handleCancelEdit', 'handleSaveEdit', and 'saveRequested'. Either include them or remove the dependency array.","line":230,"column":6,"nodeType":"ArrayExpression","endLine":230,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [clearRequested, comment.id, handleCancelEdit, handleSaveEdit, saveRequested, toolsChanged]","fix":{"range":[6634,6648],"text":"[clearRequested, comment.id, handleCancelEdit, handleSaveEdit, saveRequested, toolsChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setChanged'. Either include it or remove the dependency array.","line":237,"column":6,"nodeType":"ArrayExpression","endLine":237,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [canSaveRecording, setChanged]","fix":{"range":[6795,6813],"text":"[canSaveRecording, setChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'IsVernacularMedia' and 'memory'. Either include them or remove the dependency array.","line":302,"column":6,"nodeType":"ArrayExpression","endLine":302,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [IsVernacularMedia, mediaId, memory]","fix":{"range":[8444,8462],"text":"[IsVernacularMedia, mediaId, memory]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'CommentAuthor'. Either include it or remove the dependency array.","line":316,"column":6,"nodeType":"ArrayExpression","endLine":316,"endColumn":22,"suggestions":[{"desc":"Update the dependencies array to be: [CommentAuthor, comment, users]","fix":{"range":[8893,8909],"text":"[CommentAuthor, comment, users]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\CommentEditor.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setCommentRecording'. Either include it or remove the dependency array.","line":128,"column":6,"nodeType":"ArrayExpression","endLine":128,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [setCommentRecording]","fix":{"range":[3668,3670],"text":"[setCommentRecording]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearRequested', 'handleCancel', 'handleOk', 'isChanged', 'myChanged', and 'saveRequested'. Either include them or remove the dependency array.","line":137,"column":6,"nodeType":"ArrayExpression","endLine":137,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [toolsChanged, toolId, isChanged, myChanged, saveRequested, handleOk, clearRequested, handleCancel]","fix":{"range":[3949,3971],"text":"[toolsChanged, toolId, isChanged, myChanged, saveRequested, handleOk, clearRequested, handleCancel]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'reset'. Either include it or remove the dependency array.","line":226,"column":6,"nodeType":"ArrayExpression","endLine":226,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [refresh, reset]","fix":{"range":[6223,6232],"text":"[refresh, reset]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\DiscussionCard.addSave.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\DiscussionCard.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'DiscussionAuthor'. Either include it or remove the dependency array.","line":315,"column":5,"nodeType":"ArrayExpression","endLine":315,"endColumn":36,"suggestions":[{"desc":"Update the dependencies array to be: [DiscussionAuthor, discussion, user, userIsAdmin]","fix":{"range":[9729,9760],"text":"[DiscussionAuthor, discussion, user, userIsAdmin]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setChanged'. Either include it or remove the dependency array.","line":405,"column":6,"nodeType":"ArrayExpression","endLine":405,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [canSaveRecording, setChanged]","fix":{"range":[12338,12356],"text":"[canSaveRecording, setChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'discussion.attributes?.subject', 'editing', 'handleReset', 'onAddComplete', and 'setChanged'. Either include them or remove the dependency array.","line":418,"column":6,"nodeType":"ArrayExpression","endLine":418,"endColumn":34,"suggestions":[{"desc":"Update the dependencies array to be: [currentstep, discussion.attributes?.subject, discussion.id, editing, handleReset, onAddComplete, setChanged]","fix":{"range":[12800,12828],"text":"[currentstep, discussion.attributes?.subject, discussion.id, editing, handleReset, onAddComplete, setChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'discussion.id', 'myCommentIds', 'myToolId', 'saveCompleted', 'setChanged', and 'toolChanged'. Either include them or remove the dependency array.","line":442,"column":6,"nodeType":"ArrayExpression","endLine":442,"endColumn":43,"suggestions":[{"desc":"Update the dependencies array to be: [toolsChanged, myComments, myChanged, discussion.id, toolChanged, myToolId, setChanged, saveCompleted, myCommentIds]","fix":{"range":[13725,13762],"text":"[toolsChanged, myComments, myChanged, discussion.id, toolChanged, myToolId, setChanged, saveCompleted, myCommentIds]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'handleSave'. Either include it or remove the dependency array.","line":450,"column":6,"nodeType":"ArrayExpression","endLine":450,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [changeAssignment, handleSave]","fix":{"range":[13953,13971],"text":"[changeAssignment, handleSave]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'canAccess'. Either include it or remove the dependency array.","line":467,"column":6,"nodeType":"ArrayExpression","endLine":467,"endColumn":44,"suggestions":[{"desc":"Update the dependencies array to be: [canAccess, comments, discussion.id, permissions]","fix":{"range":[14401,14439],"text":"[canAccess, comments, discussion.id, permissions]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setAssigned'. Either include it or remove the dependency array.","line":472,"column":6,"nodeType":"ArrayExpression","endLine":472,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [discussion, setAssigned]","fix":{"range":[14604,14616],"text":"[discussion, setAssigned]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'localizedArtifactCategory'. Either include it or remove the dependency array.","line":504,"column":6,"nodeType":"ArrayExpression","endLine":504,"endColumn":37,"suggestions":[{"desc":"Update the dependencies array to be: [artifactcategorys, discussion, localizedArtifactCategory]","fix":{"range":[15568,15599],"text":"[artifactcategorys, discussion, localizedArtifactCategory]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'localizedWorkStepFromId'. Either include it or remove the dependency array.","line":511,"column":6,"nodeType":"ArrayExpression","endLine":511,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [discussion, localizedWorkStepFromId, showStep]","fix":{"range":[15857,15879],"text":"[discussion, localizedWorkStepFromId, showStep]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'mediafiles', 'passages', 'plans', and 'sections'. Either include them or remove the dependency array.","line":535,"column":6,"nodeType":"ArrayExpression","endLine":535,"endColumn":33,"suggestions":[{"desc":"Update the dependencies array to be: [discussion, mediafiles, passages, plans, sections, showReference]","fix":{"range":[16738,16765],"text":"[discussion, mediafiles, passages, plans, sections, showReference]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearRequested', 'handleCancel', 'handleSave', 'myCommentIds', 'myToolId', 'saveRequested', 'startClear', 'startSave', and 'waitForRemoteQueue'. Either include them or remove the dependency array.","line":897,"column":6,"nodeType":"ArrayExpression","endLine":897,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [clearRequested, handleCancel, handleSave, myCommentIds, myToolId, saveRequested, startClear, startSave, toolsChanged, waitForRemoteQueue]","fix":{"range":[26725,26739],"text":"[clearRequested, handleCancel, handleSave, myCommentIds, myToolId, saveRequested, startClear, startSave, toolsChanged, waitForRemoteQueue]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'discussion.id', 'handleLocate', and 'setRef'. Either include them or remove the dependency array.","line":912,"column":6,"nodeType":"ArrayExpression","endLine":912,"endColumn":71,"suggestions":[{"desc":"Update the dependencies array to be: [discussion.id, handleLocate, highlightDiscussion, myRegion?.start, refresh, requestHighlight, setRef]","fix":{"range":[27165,27230],"text":"[discussion.id, handleLocate, highlightDiscussion, myRegion?.start, refresh, requestHighlight, setRef]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'CommentAuthor', 'citGroup', 'handleGroupChange', 'handleUserChange', 'hasPermission', 'mentorGroup', and 'user'. Either include them or remove the dependency array.","line":957,"column":6,"nodeType":"ArrayExpression","endLine":957,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [CommentAuthor, citGroup, handleGroupChange, handleUserChange, hasPermission, mentorGroup, myComments, user]","fix":{"range":[28786,28798],"text":"[CommentAuthor, citGroup, handleGroupChange, handleUserChange, hasPermission, mentorGroup, myComments, user]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\DiscussionList.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getCurrentSegment'. Either include it or remove the dependency array.","line":119,"column":6,"nodeType":"ArrayExpression","endLine":119,"endColumn":22,"suggestions":[{"desc":"Update the dependencies array to be: [currentSegment, getCurrentSegment]","fix":{"range":[3999,4015],"text":"[currentSegment, getCurrentSegment]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'orgFilterState' and 'setOrgDefault'. Either include them or remove the dependency array.","line":206,"column":6,"nodeType":"ArrayExpression","endLine":206,"endColumn":32,"suggestions":[{"desc":"Update the dependencies array to be: [teamDefault, filterState, orgFilterState, setOrgDefault]","fix":{"range":[6793,6819],"text":"[teamDefault, filterState, orgFilterState, setOrgDefault]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'defaultFilterState' and 'getOrgDefault'. Either include them or remove the dependency array.","line":216,"column":6,"nodeType":"ArrayExpression","endLine":216,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [defaultFilterState, getOrgDefault, organization]","fix":{"range":[7132,7146],"text":"[defaultFilterState, getOrgDefault, organization]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'isChanged' and 'resetDiscussionList'. Either include them or remove the dependency array.","line":341,"column":6,"nodeType":"ArrayExpression","endLine":349,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [discussions, currentstep, adding, filterState, sortState, catFilter, passage, isChanged, resetDiscussionList]","fix":{"range":[11049,11160],"text":"[discussions, currentstep, adding, filterState, sortState, catFilter, passage, isChanged, resetDiscussionList]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setDiscussionMarkers' and 'theme.palette.secondary.light'. Either include them or remove the dependency array.","line":379,"column":6,"nodeType":"ArrayExpression","endLine":379,"endColumn":47,"suggestions":[{"desc":"Update the dependencies array to be: [displayDiscussions, mediafileId, adding, setDiscussionMarkers, theme.palette.secondary.light]","fix":{"range":[11956,11997],"text":"[displayDiscussions, mediafileId, adding, setDiscussionMarkers, theme.palette.secondary.light]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'discussionOrg', 'organization', and 't.filterStatus'. Either include them or remove the dependency array.","line":511,"column":5,"nodeType":"ArrayExpression","endLine":511,"endColumn":38,"suggestions":[{"desc":"Update the dependencies array to be: [t.filterStatus, displayDiscussions.length, discussions, discussionOrg, organization]","fix":{"range":[15637,15670],"text":"[t.filterStatus, displayDiscussions.length, discussions, discussionOrg, organization]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\DiscussionMenu.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\DiscussionMove.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\DiscussionPanel.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\FilterMenu.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\FilterResolved.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\ReplyCard.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearRequested', 'handleCancelEdit', 'handleSaveEdit', 'myToolId', and 'saveRequested'. Either include them or remove the dependency array.","line":111,"column":6,"nodeType":"ArrayExpression","endLine":111,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [clearRequested, handleCancelEdit, handleSaveEdit, myToolId, saveRequested, toolsChanged]","fix":{"range":[3502,3516],"text":"[clearRequested, handleCancelEdit, handleSaveEdit, myToolId, saveRequested, toolsChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setChanged'. Either include it or remove the dependency array.","line":128,"column":6,"nodeType":"ArrayExpression","endLine":128,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [canSaveRecording, setChanged]","fix":{"range":[3938,3956],"text":"[canSaveRecording, setChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\SortMenu.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\discussionCardTopicStyles.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\discussionCardTopicStyles.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\startAudioCommentSave.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\startAudioCommentSave.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Discussions\\useRecordComment.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ErrorFallback.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ErrorPage.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'ctx', 'errorReporter', and 'state'. Either include them or remove the dependency array. You can also do a functional update 'setState(s => ...)' if you only need 'state' in the 'setState' call.","line":229,"column":6,"nodeType":"ArrayExpression","endLine":229,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [ctx, error, errorReporter, state]","fix":{"range":[6695,6702],"text":"[ctx, error, errorReporter, state]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ExportActionCell.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ExtendableDeleteExpansion.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ExternalLink.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'handleLaunch' and 'register'. Either include them or remove the dependency array.","line":32,"column":6,"nodeType":"ArrayExpression","endLine":32,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [handleLaunch, register]","fix":{"range":[884,886],"text":"[handleLaunch, register]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'finish'. Either include it or remove the dependency array.","line":41,"column":6,"nodeType":"ArrayExpression","endLine":41,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [externalUrl, finish]","fix":{"range":[1113,1126],"text":"[externalUrl, finish]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\FilterContent.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\FontSize.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\GraphicImageFilter.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\GraphicPicker.categoryDefault.test.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'disableTypography' is defined but never used. Allowed unused args must match /^_/u.","line":75,"column":5,"nodeType":null,"messageId":"unusedVar","endLine":75,"endColumn":22}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import React from 'react';\nimport {\n act,\n fireEvent,\n render,\n screen,\n waitFor,\n} from '@testing-library/react';\nimport GraphicPicker, { NOTE_CATEGORY_STYLE } from './GraphicPicker';\n\n// Regression for TT-7703: Edit Team Categories opens Graphic Picker with\n// Note Category checked as the Default filter; Clear clears it; Reset to\n// Default restores it. Scripture-plan opens must not check that style.\n// The graphics API returns \"Note category\" (lowercase c); defaults must\n// rematch that canonical casing so the checkbox and search agree.\n// GraphicImageFilter is NOT mocked so Styles checkboxes can be asserted.\n\njest.mock('../context/useGlobal', () => ({\n useGlobal: () => [undefined, jest.fn()],\n}));\n\njest.mock('../crud', () => ({\n useOrganizedBy: () => ({\n getOrganizedBy: () => 'Section',\n }),\n}));\n\nconst STYLE_URL = 'https://graphics.example.com/api/styles';\nconst SEARCH_URL_BASE = 'https://graphics.example.com/api/search';\n\n/** Canonical spelling returned by the graphics /styles API (screenshot / prod). */\nconst API_NOTE_CATEGORY_STYLE = 'Note category';\n\njest.mock('../crud/useGraphicUrlBuilder', () => {\n const getSearchUrl = ({\n filterState,\n }: {\n filterState?: { s?: string; k?: string };\n }) => {\n const params = new URLSearchParams();\n if (filterState?.s) params.set('s', filterState.s);\n if (filterState?.k) params.set('k', filterState.k);\n const q = params.toString();\n return q ? `${SEARCH_URL_BASE}?${q}` : SEARCH_URL_BASE;\n };\n const getKeywordUrl = () => undefined;\n const getStyleUrl = () => STYLE_URL;\n const refFromQuery = (q: string) => q;\n return {\n useGraphicUrlBuilder: () => ({\n getSearchUrl,\n getKeywordUrl,\n getStyleUrl,\n refFromQuery,\n }),\n };\n});\n\njest.mock('../utils/useCompression', () => ({\n useCompression: () => ({ uploadMedia: jest.fn(), showFile: jest.fn() }),\n}));\n\njest.mock('../utils/useDebounce', () => ({\n useDebounce: (v: string) => v,\n}));\n\njest.mock('../utils/logErrorService', () => ({\n __esModule: true,\n default: jest.fn(),\n Severity: { error: 'error' },\n}));\n\njest.mock('../control', () => ({\n Button: ({\n disableTypography,\n ...props\n }: React.ButtonHTMLAttributes & {\n disableTypography?: boolean;\n }) => \n
\n );\n },\n };\n});\n\njest.mock('./GraphicRights', () => ({\n __esModule: true,\n default: ({ value }: { value?: string }) =>
rights:{value}
,\n}));\n\nconst graphicStrings = {\n tabBible: 'Library',\n tabCustom: 'Custom',\n tabCurrent: 'Current',\n graphicSource: 'graphic source tabs',\n title: 'Graphic Picker',\n graphicSearch: 'Search graphics',\n noSelection: 'no {0} selected.',\n noResults: 'No matching images found.',\n loadFailure: 'Failed to load',\n keywordSearchHint: 'keyword hint',\n setGraphic: 'Set as Graphic',\n graphicDisplay: 'Display current graphic',\n};\n\nconst sharedStrings = {\n cancel: 'Cancel',\n};\n\njest.mock('react-redux', () => ({\n ...jest.requireActual('react-redux'),\n useSelector: jest.fn((sel: (s: unknown) => unknown) =>\n sel({\n strings: { graphic: graphicStrings, shared: sharedStrings },\n books: { bookData: [] },\n })\n ),\n shallowEqual: (a: unknown, b: unknown) => a === b,\n}));\n\njest.mock('../selector', () => ({\n graphicStringsSelector: (state: {\n strings: { graphic: typeof graphicStrings };\n }) => state.strings.graphic,\n sharedSelector: (state: { strings: { shared: typeof sharedStrings } }) =>\n state.strings.shared,\n}));\n\nconst baseProps = {\n isOpen: true,\n onOpen: jest.fn(),\n cancelled: { current: false },\n showMessage: jest.fn(),\n dimension: [40],\n finish: jest.fn(),\n};\n\ndescribe('GraphicPicker', () => {\n it('shows no-selection when scripture context is missing', () => {\n render();\n expect(screen.getByText('no Section selected.')).toBeInTheDocument();\n expect(screen.queryByLabelText('Search graphics')).not.toBeInTheDocument();\n });\n\n it('shows the library search when scripture is false', () => {\n render();\n expect(screen.getByLabelText('Search graphics')).toBeInTheDocument();\n expect(screen.queryByText(/no .* selected/i)).not.toBeInTheDocument();\n expect(screen.getByText('Library')).toBeInTheDocument();\n expect(screen.getByText('Custom')).toBeInTheDocument();\n });\n\n it('shows the current graphic on the Current tab', async () => {\n render(\n \n );\n await waitFor(() => {\n expect(screen.getByAltText('Display current graphic')).toHaveAttribute(\n 'src',\n 'https://example.com/g.jpg'\n );\n });\n expect(screen.getByText('SIL')).toBeInTheDocument();\n });\n\n it('does not close-save when Custom Set Graphic starts an upload', () => {\n const { mockHandleAddOrSave } = jest.requireMock('./GraphicUploader') as {\n mockHandleAddOrSave: jest.Mock;\n };\n mockHandleAddOrSave.mockClear();\n const onOpen = jest.fn();\n render();\n fireEvent.click(screen.getByRole('tab', { name: 'Custom' }));\n fireEvent.click(screen.getByRole('button', { name: 'Set as Graphic' }));\n expect(mockHandleAddOrSave).toHaveBeenCalledTimes(1);\n expect(onOpen).not.toHaveBeenCalled();\n });\n\n it('reseeds Custom rights when currentRights updates while open', () => {\n const { rerender } = render(\n \n );\n fireEvent.click(screen.getByRole('tab', { name: 'Custom' }));\n expect(screen.getByText('rights:cached')).toBeInTheDocument();\n rerender(\n \n );\n expect(screen.getByText('rights:fresh')).toBeInTheDocument();\n });\n\n it('revokes blob preview URLs when replaced or closed', () => {\n const create = jest\n .fn()\n .mockReturnValueOnce('blob:preview-1')\n .mockReturnValueOnce('blob:preview-2');\n const revoke = jest.fn();\n Object.defineProperty(URL, 'createObjectURL', {\n configurable: true,\n writable: true,\n value: create,\n });\n Object.defineProperty(URL, 'revokeObjectURL', {\n configurable: true,\n writable: true,\n value: revoke,\n });\n const { rerender } = render(\n \n );\n fireEvent.click(screen.getByRole('tab', { name: 'Custom' }));\n fireEvent.click(screen.getByRole('button', { name: 'pick-file' }));\n fireEvent.click(screen.getByRole('button', { name: 'pick-file' }));\n expect(revoke).toHaveBeenCalledWith('blob:preview-1');\n rerender();\n expect(revoke).toHaveBeenCalledWith('blob:preview-2');\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\GraphicPicker.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'tabValue'. Either include it or remove the dependency array.","line":491,"column":6,"nodeType":"ArrayExpression","endLine":491,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [hasCurrent, tabValue]","fix":{"range":[14719,14731],"text":"[hasCurrent, tabValue]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'errorReporter'. Either include it or remove the dependency array.","line":753,"column":6,"nodeType":"ArrayExpression","endLine":761,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [tabValue, selectedId, images, onSelectedRights, dimension, finish, onOpen, errorReporter]","fix":{"range":[23381,23489],"text":"[tabValue, selectedId, images, onSelectedRights, dimension, finish, onOpen, errorReporter]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\GraphicRights.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'props.onInputValueChange', 'setValue', 'value?.inputValue', and 'value?.title'. Either include them or remove the dependency array.","line":125,"column":6,"nodeType":"ArrayExpression","endLine":125,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [props.onInputValueChange, props.value, setValue, value?.inputValue, value?.title]","fix":{"range":[3932,3945],"text":"[props.onInputValueChange, props.value, setValue, value?.inputValue, value?.title]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react/prop-types","severity":2,"message":"'key' is missing in props validation","line":162,"column":19,"nodeType":"Property","messageId":"missingPropType","endLine":162,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\GraphicUploader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\GroupAvatar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\GroupTabs.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\HTMLPage.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\HelpMenu.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":161,"column":5,"severity":1,"nodeType":null,"fix":{"range":[5228,5283],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has missing dependencies: 'getPlan' and 'memory?.keyMap'. Either include them or remove the dependency array.","line":141,"column":5,"nodeType":"ArrayExpression","endLine":141,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [getPlan, memory?.keyMap, pathname]","fix":{"range":[4716,4726],"text":"[getPlan, memory?.keyMap, pathname]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has missing dependencies: 't.flatSample', 't.genFlatSample', 't.genHierarchicalSample', and 't.hierarchicalSample'. Either include them or remove the dependency array.","line":181,"column":6,"nodeType":"ArrayExpression","endLine":181,"endColumn":62,"suggestions":[{"desc":"Update the dependencies array to be: [planRec, projType, t.flatSample, t.genFlatSample, t.genHierarchicalSample, t.hierarchicalSample]","fix":{"range":[5793,5849],"text":"[planRec, projType, t.flatSample, t.genFlatSample, t.genHierarchicalSample, t.hierarchicalSample]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked.","line":181,"column":26,"nodeType":"ChainExpression","endLine":181,"endColumn":61,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import React from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { useGetGlobal, useGlobal } from '../context/useGlobal';\nimport { IMainStrings, Plan } from '../model';\nimport { IconButton, ListItemIcon, ListItemText, SxProps } from '@mui/material';\nimport ReportIcon from '@mui/icons-material/Report';\nimport NotesIcon from '@mui/icons-material/SpeakerNotes';\nimport BooksIcon from '@mui/icons-material/LibraryBooks';\nimport TrainingIcon from '@mui/icons-material/FlightClass';\nimport HelpOutlineIcon from '@mui/icons-material/HelpOutline';\nimport InfoIcon from '@mui/icons-material/Info';\nimport DownloadIcon from '@mui/icons-material/CloudDownload';\nimport FolderIcon from '@mui/icons-material/Folder';\nimport AddIcon from '@mui/icons-material/Add';\nimport RemoveIcon from '@mui/icons-material/Remove';\nimport { AkuoLogo } from '../control/akuoLogo';\nimport { LogosIcon } from '../control/logosIcon';\nimport { StyledMenu, StyledMenuItem } from '../control';\nimport path from 'path-browserify';\nimport { isElectron, API_CONFIG } from '../../api-variable';\nimport {\n launch,\n dataPath,\n PathType,\n execFolder,\n restoreScroll,\n} from '../utils';\nimport { useSnackBar } from '../hoc/SnackBar';\nimport AboutDialog from './AboutDialog';\nimport { usePlan, remoteIdGuid } from '../crud';\nimport { mainSelector } from '../selector';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport { ContextHelp } from './ContextHelp';\nimport { RecordKeyMap } from '@orbit/records';\nimport {\n Akuo,\n Logos,\n TranslatorsNotes,\n TranslatorsWorkplace,\n UbsResources,\n} from '../assets/brands';\nimport TwIcon from '../control/twIcon';\nimport { MainAPI } from '@model/main-api';\nconst ipc = window?.api as MainAPI;\n\nconst logosAppUri = 'https://app.logos.com/';\nconst twInstallUri = 'https://www.sil.org/resources/publications/tw';\n\ninterface IProps {\n online: boolean;\n action?: (what: string) => void;\n sx?: SxProps;\n}\n\nexport function HelpMenu(props: IProps) {\n const { online, action } = props;\n const { pathname } = useLocation();\n const [projType] = useGlobal('projType'); //verified this is not used in a function 2/18/25\n const [memory] = useGlobal('memory');\n const [anchorEl, setAnchorEl] = React.useState(null);\n const [shift, setShift] = React.useState(false);\n const [developer, setDeveloper] = useGlobal('developer');\n const [aboutOpen, setAboutOpen] = React.useState(false);\n const [topic, setTopic] = React.useState();\n const { showMessage } = useSnackBar();\n const { getPlan } = usePlan();\n const t: IMainStrings = useSelector(mainSelector, shallowEqual);\n const getGlobal = useGetGlobal();\n const handleClick = (event: React.MouseEvent) => {\n setShift(event.shiftKey);\n setAnchorEl(event.currentTarget);\n };\n\n const handleHelp = (topic: string) => () => {\n setTopic(topic);\n setAnchorEl(null);\n };\n\n const handleReset = () => {\n setTopic(undefined);\n };\n\n const handleDownload = (url: string, inOffline?: boolean) => async () => {\n const loc = inOffline !== undefined ? inOffline : getGlobal('offline');\n const urlObj = new URL(url);\n const name = urlObj.pathname.split('/').pop() || '';\n const folder = await execFolder();\n const localPath = loc\n ? path.join(folder, 'help', name)\n : await dataPath(name, PathType.ZIP);\n if (!loc) {\n const err = await ipc?.downloadFile(url, localPath);\n if (err || !(await ipc?.exists(localPath))) {\n showMessage(`Failed to download ${name}`);\n setAnchorEl(null);\n return;\n }\n }\n launch(localPath, false);\n setAnchorEl(null);\n if (action) action('Download');\n };\n\n const handleSite = (site: string) => () => {\n if (!online) showMessage(t.reportWhenOnline);\n else launch(site, online);\n };\n\n const handleDeveloper = () => {\n const newVal = developer ? false : true;\n localStorage.setItem('developer', newVal.toString());\n setDeveloper(newVal);\n setAnchorEl(null);\n };\n\n const handleAbout = (visible: boolean) => () => {\n if (visible !== aboutOpen) setAboutOpen(visible);\n restoreScroll();\n setAnchorEl(null);\n };\n\n const handle = (what: string) => () => {\n setAnchorEl(null);\n if (action) {\n action(what);\n }\n };\n\n const spreadsheetTopic = '#t=Concepts%2FSpreadsheet_convention.htm';\n\n const planRec = React.useMemo(\n () => {\n const match = /\\/plan\\/([0-9a-f-]+)\\/0/.exec(pathname);\n const planId =\n match &&\n (remoteIdGuid('plan', match[1] ?? '', memory?.keyMap as RecordKeyMap) ||\n match[1]);\n return planId && getPlan(planId);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [pathname]\n );\n\n const sampleHref = React.useMemo(\n () => {\n if (!planRec) return '#';\n if (planRec.attributes.flat) {\n if (projType.toLowerCase() === 'scripture') {\n return API_CONFIG.flatSample;\n } else {\n return API_CONFIG.genFlatSample;\n }\n } else {\n if (projType.toLowerCase() === 'scripture') {\n return API_CONFIG.hierarchicalSample;\n } else {\n return API_CONFIG.genHierarchicalSample;\n }\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [planRec, projType]\n );\n\n const sampleDesc = React.useMemo(() => {\n if (!planRec) return '';\n if (planRec.attributes.flat) {\n if (projType.toLowerCase() === 'scripture') {\n return t.flatSample;\n } else {\n return t.genFlatSample;\n }\n } else {\n if (projType.toLowerCase() === 'scripture') {\n return t.hierarchicalSample;\n } else {\n return t.genHierarchicalSample;\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [planRec, projType, (planRec as Plan)?.attributes?.flat]);\n\n return (\n
\n \n \n \n \n \n \n \n \n \n \n {planRec && (\n \n \n \n \n \n \n )}\n {planRec && !isElectron && (\n \n \n \n \n \n \n \n \n )}\n {planRec && isElectron && (\n \n \n \n \n \n \n )}\n {planRec && isElectron && (\n \n \n \n \n \n \n )}\n {planRec && !isElectron && (\n \n \n \n \n \n \n \n \n )}\n {isElectron && (\n \n \n \n \n \n \n )}\n {!isElectron && (\n \n \n \n \n \n \n \n \n )}\n {isElectron && (\n \n \n \n \n \n \n )}\n {!isElectron && (\n \n \n \n \n \n \n \n \n )}\n {isElectron && (\n \n \n \n \n \n \n )}\n {!isElectron && (\n \n \n \n \n \n \n \n \n )}\n {isElectron && (\n \n \n \n \n \n \n )}\n {!isElectron && (\n \n \n \n \n \n \n \n \n )}\n {isElectron && (\n \n \n \n \n \n \n )}\n {!isElectron && (\n \n \n \n \n \n \n \n \n )}\n {isElectron && (\n \n \n \n \n \n \n )}\n {!isElectron && (\n \n \n \n \n \n \n \n \n )}\n {isElectron && (\n \n \n \n \n \n \n )}\n {!isElectron && (\n \n \n \n \n \n \n \n \n )}\n {isElectron && (\n \n \n \n \n \n \n )}\n {!isElectron && (\n \n \n \n \n \n \n \n \n )}\n {isElectron && (\n \n \n \n \n \n \n )}\n {!isElectron && (\n \n \n \n \n \n \n \n \n )}\n {shift && (\n \n \n {developer ? : }\n \n \n \n )}\n {isElectron && (\n \n \n \n \n \n \n )}\n {!isElectron && (\n \n \n \n \n \n \n \n \n )}\n \n \n \n \n \n \n \n \n \n
\n );\n}\n\nexport default HelpMenu;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\HiddenPlayer.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ImportTab.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"The 'sortModel' array makes the dependencies of useMemo Hook (at line 368) change on every render. Move it inside the useMemo callback. Alternatively, wrap the initialization of 'sortModel' in its own useMemo() Hook.","line":357,"column":9,"nodeType":"VariableDeclarator","endLine":360,"endColumn":4,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getImportFile', 'isOffline', 'offerPtf', 'syncBuffer', 'syncFile', and 'uploadSyncITF'. Either include them or remove the dependency array.","line":391,"column":6,"nodeType":"ArrayExpression","endLine":391,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [getImportFile, isOffline, offerPtf, syncBuffer, syncFile, uploadSyncITF]","fix":{"range":[11590,11592],"text":"[getImportFile, isOffline, offerPtf, syncBuffer, syncFile, uploadSyncITF]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'changeData', 'forceDataChanges', 'getChangeData', 'handleClose', 'importTitle', 'memory', 'remote', 'setImporting', 'setLanguage', 'syncFile', 't.importComplete', 't.importSyncDown', 't.onlineChangeReport', 'translateError', and 'user'. Either include them or remove the dependency array.","line":1076,"column":6,"nodeType":"ArrayExpression","endLine":1076,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [changeData, forceDataChanges, getChangeData, handleClose, importStatus, importTitle, memory, remote, setImporting, setLanguage, syncFile, t.importComplete, t.importSyncDown, t.onlineChangeReport, translateError, user]","fix":{"range":[33996,34010],"text":"[changeData, forceDataChanges, getChangeData, handleClose, importStatus, importTitle, memory, remote, setImporting, setLanguage, syncFile, t.importComplete, t.importSyncDown, t.onlineChangeReport, translateError, user]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Integration.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'checkOnline', 'local', and 'resetProjects'. Either include them or remove the dependency array.","line":578,"column":6,"nodeType":"ArrayExpression","endLine":578,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [checkOnline, local, resetProjects]","fix":{"range":[17946,17948],"text":"[checkOnline, local, resetProjects]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'resetCount', 'resetProjects', 'resetSync', and 'resetUserName'. Either include them or remove the dependency array.","line":588,"column":6,"nodeType":"ArrayExpression","endLine":588,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [resetCount, resetProjects, resetSync, resetUserName]","fix":{"range":[18151,18153],"text":"[resetCount, resetProjects, resetSync, resetUserName]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'resetUserName'. Either include it or remove the dependency array.","line":594,"column":6,"nodeType":"ArrayExpression","endLine":594,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [resetUserName, user]","fix":{"range":[18290,18296],"text":"[resetUserName, user]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'resetUserName'. Either include it or remove the dependency array.","line":599,"column":6,"nodeType":"ArrayExpression","endLine":599,"endColumn":30,"suggestions":[{"desc":"Update the dependencies array to be: [connected, hasParatext, resetUserName]","fix":{"range":[18437,18461],"text":"[connected, hasParatext, resetUserName]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'myProject', 'resetCount', 'resetProjects', and 'resetSync'. Either include them or remove the dependency array.","line":612,"column":6,"nodeType":"ArrayExpression","endLine":612,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [myProject, project, resetCount, resetProjects, resetSync]","fix":{"range":[18764,18773],"text":"[myProject, project, resetCount, resetProjects, resetSync]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'errorReporter', 'getLocalCount', 'getTypeId', 'memory', 'passage?.id', 'resetCount', and 't'. Either include them or remove the dependency array.","line":630,"column":6,"nodeType":"ArrayExpression","endLine":630,"endColumn":36,"suggestions":[{"desc":"Update the dependencies array to be: [mediafiles, plan, exportType, resetCount, getLocalCount, memory, errorReporter, t, getTypeId, passage?.id]","fix":{"range":[19116,19146],"text":"[mediafiles, plan, exportType, resetCount, getLocalCount, memory, errorReporter, t, getTypeId, passage?.id]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getParatextIntegration' and 'offlineOnly'. Either include them or remove the dependency array.","line":637,"column":6,"nodeType":"ArrayExpression","endLine":637,"endColumn":32,"suggestions":[{"desc":"Update the dependencies array to be: [integrations, exportType, getParatextIntegration, offlineOnly]","fix":{"range":[19351,19377],"text":"[integrations, exportType, getParatextIntegration, offlineOnly]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'isMounted', 'organizedBy', 'paratext_count', 'resetCount', 'showTitledMessage', 't.countError', and 'ts'. Either include them or remove the dependency array.","line":655,"column":6,"nodeType":"ArrayExpression","endLine":655,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [isMounted, organizedBy, paratext_count, paratext_countStatus, resetCount, showTitledMessage, t.countError, ts]","fix":{"range":[19912,19934],"text":"[isMounted, organizedBy, paratext_count, paratext_countStatus, resetCount, showTitledMessage, t.countError, ts]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'accessToken', 'errorReporter', 'getUserName', 'isMounted', 'local', 'organizedBy', 'showTitledMessage', 't.usernameError', 't.usernamePending', and 'ts'. Either include them or remove the dependency array.","line":670,"column":6,"nodeType":"ArrayExpression","endLine":670,"endColumn":50,"suggestions":[{"desc":"Update the dependencies array to be: [accessToken, errorReporter, getUserName, isMounted, local, organizedBy, paratext_username, paratext_usernameStatus, showTitledMessage, t.usernameError, t.usernamePending, ts]","fix":{"range":[20418,20462],"text":"[accessToken, errorReporter, getUserName, isMounted, local, organizedBy, paratext_username, paratext_usernameStatus, showTitledMessage, t.usernameError, t.usernamePending, ts]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'accessToken', 'errorReporter', 'findConnectedProject', 'getLocalProjects', 'getProject', 'getProjects', 'isMounted', 'local', 'memory?.keyMap', 'organizedBy', 'projectintegrations', 'showTitledMessage', 't.projectError', 't.projectsPending', and 'ts'. Either include them or remove the dependency array.","line":724,"column":6,"nodeType":"ArrayExpression","endLine":724,"endColumn":77,"suggestions":[{"desc":"Update the dependencies array to be: [busy, paratext_projects, paratext_projectsStatus, paratextIntegration, getProject, local, projectintegrations, memory?.keyMap, getLocalProjects, t.projectsPending, t.projectError, getProjects, accessToken, errorReporter, isMounted, showTitledMessage, ts, organizedBy, findConnectedProject]","fix":{"range":[22128,22199],"text":"[busy, paratext_projects, paratext_projectsStatus, paratextIntegration, getProject, local, projectintegrations, memory?.keyMap, getLocalProjects, t.projectsPending, t.projectError, getProjects, accessToken, errorReporter, isMounted, showTitledMessage, ts, organizedBy, findConnectedProject]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'findConnectedProject' and 'paratext_projectsStatus?.complete'. Either include them or remove the dependency array.","line":731,"column":6,"nodeType":"ArrayExpression","endLine":731,"endColumn":76,"suggestions":[{"desc":"Update the dependencies array to be: [projectintegrations, paratext_projects, paratextIntegration, project, paratext_projectsStatus?.complete, findConnectedProject]","fix":{"range":[22382,22452],"text":"[projectintegrations, paratext_projects, paratextIntegration, project, paratext_projectsStatus?.complete, findConnectedProject]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'TranslateSyncError', 'currentstep', 'forceDataChanges', 'gotoNextStep', 'isMounted', 'resetCount', 'resetSync', 'setStepComplete', 'showMessage', 'showTitledMessage', and 't.syncError'. Either include them or remove the dependency array.","line":756,"column":6,"nodeType":"ArrayExpression","endLine":756,"endColumn":27,"suggestions":[{"desc":"Update the dependencies array to be: [TranslateSyncError, currentstep, forceDataChanges, gotoNextStep, isMounted, paratext_syncStatus, resetCount, resetSync, setStepComplete, showMessage, showTitledMessage, t.syncError]","fix":{"range":[23358,23379],"text":"[TranslateSyncError, currentstep, forceDataChanges, gotoNextStep, isMounted, paratext_syncStatus, resetCount, resetSync, setStepComplete, showMessage, showTitledMessage, t.syncError]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\InvitationTable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Invite.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'currentUser'. Either include it or remove the dependency array.","line":231,"column":6,"nodeType":"ArrayExpression","endLine":231,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [currentUser, user, users]","fix":{"range":[6368,6381],"text":"[currentUser, user, users]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'allUsersProjects', 'email', 'organization', 'projects', 'resetFields', 'role', and 't.noProjects'. Either include them or remove the dependency array.","line":256,"column":6,"nodeType":"ArrayExpression","endLine":256,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [inviteIn, groups, organization, projects, t.noProjects, allUsersProjects, email, role, resetFields]","fix":{"range":[7203,7221],"text":"[inviteIn, groups, organization, projects, t.noProjects, allUsersProjects, email, role, resetFields]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'hasInvite', 'inviteIn', 't.alreadyInvited', and 't.invalidEmail'. Either include them or remove the dependency array.","line":276,"column":6,"nodeType":"ArrayExpression","endLine":276,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [email, hasInvite, inviteIn, t.alreadyInvited, t.invalidEmail]","fix":{"range":[7728,7735],"text":"[email, hasInvite, inviteIn, t.alreadyInvited, t.invalidEmail]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\LimitedMediaPlayer.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":2,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":2,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\LimitedMediaPlayer.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'blobState?.id', 'fetchBlob', 'ready', and 'resetMediaTiming'. Either include them or remove the dependency array.","line":172,"column":6,"nodeType":"ArrayExpression","endLine":172,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [blobState?.id, fetchBlob, ready, resetMediaTiming, srcMediaId]","fix":{"range":[4677,4689],"text":"[blobState?.id, fetchBlob, ready, resetMediaTiming, srcMediaId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'stopPlay'. Either include it or remove the dependency array.","line":177,"column":6,"nodeType":"ArrayExpression","endLine":177,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [blobState.id, stopPlay]","fix":{"range":[4794,4808],"text":"[blobState.id, stopPlay]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'onLoaded' and 'ready'. Either include them or remove the dependency array.","line":185,"column":6,"nodeType":"ArrayExpression","endLine":185,"endColumn":17,"suggestions":[{"desc":"Update the dependencies array to be: [blobState, onLoaded, ready]","fix":{"range":[5020,5031],"text":"[blobState, onLoaded, ready]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'startPlay' and 'stopPlay'. Either include them or remove the dependency array.","line":194,"column":6,"nodeType":"ArrayExpression","endLine":194,"endColumn":26,"suggestions":[{"desc":"Update the dependencies array to be: [ready, requestPlay, startPlay, stopPlay]","fix":{"range":[5226,5246],"text":"[ready, requestPlay, startPlay, stopPlay]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setPosition'. Either include it or remove the dependency array.","line":199,"column":6,"nodeType":"ArrayExpression","endLine":199,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [limits.start, setPosition]","fix":{"range":[5366,5380],"text":"[limits.start, setPosition]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\LoadAndPLay.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchMediaUrl' and 'playItem'. Either include them or remove the dependency array.","line":58,"column":6,"nodeType":"ArrayExpression","endLine":58,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [fetchMediaUrl, playItem, srcMediaId]","fix":{"range":[1834,1846],"text":"[fetchMediaUrl, playItem, srcMediaId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'onEnded', 'showMessage', 'srcMediaId', and 'ts.fileNotFound'. Either include them or remove the dependency array.","line":80,"column":6,"nodeType":"ArrayExpression","endLine":80,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [mediaState, onEnded, showMessage, srcMediaId, ts.fileNotFound]","fix":{"range":[2533,2545],"text":"[mediaState, onEnded, showMessage, srcMediaId, ts.fileNotFound]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'togglePlay'. Either include it or remove the dependency array.","line":92,"column":6,"nodeType":"ArrayExpression","endLine":92,"endColumn":45,"suggestions":[{"desc":"Update the dependencies array to be: [ready, requestPlay, playing, playItem, togglePlay]","fix":{"range":[2900,2939],"text":"[ready, requestPlay, playing, playItem, togglePlay]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\MediaDisplay.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchMediaUrl', 'mediaState.id', and 'props'. Either include them or remove the dependency array.","line":32,"column":6,"nodeType":"ArrayExpression","endLine":32,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [fetchMediaUrl, mediaState.id, props, srcMediaId]","fix":{"range":[1105,1117],"text":"[fetchMediaUrl, mediaState.id, props, srcMediaId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'showMessage', 'srcMediaId', and 'ts.fileNotFound'. Either include them or remove the dependency array.","line":44,"column":6,"nodeType":"ArrayExpression","endLine":44,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [mediaState, showMessage, srcMediaId, ts.fileNotFound]","fix":{"range":[1553,1565],"text":"[mediaState, showMessage, srcMediaId, ts.fileNotFound]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\MediaPlayer.test.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":61,"column":3,"severity":1,"nodeType":null,"fix":{"range":[1302,1363],"text":" "}}],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":2,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":2,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport React from 'react';\n// See: https://www.w3schools.com/TAGS/ref_av_dom.asp\nimport { cleanup, render, waitFor } from '@testing-library/react';\nimport { MediaPlayer } from './MediaPlayer';\nimport { act } from 'react';\nimport { HiddenPlayerProps } from './HiddenPlayer';\n\nenum MediaSt {\n IDLE,\n PENDING,\n FETCHED,\n ERROR,\n}\ninterface IMediaState {\n status: MediaSt;\n error: null | string;\n url: string; // temporary url\n id: string; // media id\n remoteId: string;\n cancelled: boolean;\n}\n\nenum BlobStatus {\n IDLE,\n PENDING,\n RESET,\n FETCHED,\n ERROR,\n}\n\ninterface IBlobState extends IMediaState {\n blob: Blob;\n blobStat: BlobStatus;\n}\n\nconst mediaClean = {\n status: MediaSt.IDLE,\n error: null,\n url: '',\n id: '',\n remoteId: '',\n cancelled: false,\n};\nconst mockBlobClean = {\n ...mediaClean,\n blob: new Blob(),\n blobStat: BlobStatus.IDLE,\n};\nlet mockMediaState: IMediaState = { ...mediaClean };\nlet mockBlobState: IBlobState = { ...mockBlobClean };\nconst mockFetchBlob = jest.fn();\nconst mockShowMessage = jest.fn();\nlet mockShouldUseWaveSurfer = false;\n\njest.mock('../utils/audioPlayback', () => ({\n shouldUseWaveSurferPlayback: jest.fn(() => mockShouldUseWaveSurfer),\n}));\n\njest.mock('./HiddenPlayer', () => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const MockHiddenPlayer = (_props: HiddenPlayerProps) => {\n return
;\n };\n MockHiddenPlayer.displayName = 'MockHiddenPlayer';\n return MockHiddenPlayer;\n});\n\njest.mock('../crud/useFetchMediaBlob', () => {\n const BlobStatus = {\n IDLE: 0,\n PENDING: 1,\n RESET: 2,\n FETCHED: 3,\n ERROR: 4,\n };\n return {\n useFetchMediaBlob: () => [mockBlobState, mockFetchBlob],\n BlobStatus,\n };\n});\n\njest.mock('../crud', () => {\n const MediaSt = {\n IDLE: 0,\n PENDING: 1,\n FETCHED: 2,\n ERROR: 3,\n };\n return {\n useFetchMediaUrl: () => {\n return {\n mediaState: mockMediaState,\n fetchMediaUrl: ({ id }: { id: string }) => {\n if (id === '1') {\n mockMediaState = {\n ...mockMediaState,\n id: 'abcd-1',\n remoteId: '1',\n error: '',\n status: MediaSt.PENDING,\n };\n setTimeout(() => {\n mockMediaState = {\n ...mockMediaState,\n status: MediaSt.FETCHED,\n url: 'https://localhost/media/1.mp3',\n };\n }, 500);\n } else if (id === 'ogg-1') {\n mockMediaState = {\n ...mockMediaState,\n id: 'abcd-ogg',\n remoteId: 'ogg-1',\n error: '',\n status: MediaSt.FETCHED,\n url: 'https://localhost/media/1.ogg',\n };\n } else {\n mockMediaState = { ...mockMediaState, error: 'error' };\n }\n },\n };\n },\n MediaSt,\n };\n});\n\njest.mock('../hoc/SnackBar', () => ({\n useSnackBar: () => ({\n showMessage: mockShowMessage,\n }),\n}));\n\njest.mock('../selector', () => ({\n peerCheckSelector: jest.fn(),\n sharedSelector: jest.fn(),\n}));\n\njest.mock('react-redux', () => ({\n useSelector: () => ({\n afterResource: 'Play from end of resource',\n back3Seconds: 'Skip back 3 seconds',\n resourceStart: 'Play from start of resource',\n mediaError: 'Media error',\n fileNotFound: 'File not found',\n close: 'Close',\n }),\n shallowEqual: jest.fn(),\n}));\n\njest.mock('../context/useGlobal', () => ({\n useGlobal: (key: string) => {\n const mockValues: Record = {\n errorReporter: jest.fn(),\n memory: {\n keyMap: { keyToId: jest.fn(), idToKey: jest.fn() },\n cache: {\n query: jest.fn(() => ({\n attributes: { contentType: 'audio/mpeg' },\n })),\n },\n update: jest.fn(),\n },\n user: 'test-user',\n organization: 'test-org',\n project: 'test-project',\n plan: 'test-plan',\n offline: false,\n };\n return [mockValues[key] || jest.fn(), jest.fn()];\n },\n}));\n\njest.mock('../schema', () => ({\n memory: {\n cache: { query: jest.fn(() => []) },\n update: jest.fn(),\n },\n requestedSchema: 100,\n}));\n\njest.mock('../utils', () => {\n const logError = jest.fn(() => {});\n return {\n logError,\n Severity: { error: 'error' },\n };\n});\n\ndescribe('', () => {\n beforeEach(() => {\n cleanup();\n mockShouldUseWaveSurfer = false;\n mockFetchBlob.mockClear();\n mockShowMessage.mockClear();\n if (!URL.revokeObjectURL) {\n Object.defineProperty(URL, 'revokeObjectURL', {\n configurable: true,\n value: jest.fn(),\n });\n }\n });\n afterEach(() => {\n mockMediaState = { ...mediaClean };\n mockBlobState = { ...mockBlobClean };\n });\n\n it('should render without crashing', () => {\n const props = {\n srcMediaId: '1',\n requestPlay: false,\n onEnded: () => {},\n };\n const { container } = render();\n expect(container.firstChild).toBe(null);\n });\n\n it('should render without crashing when requestPlay is true', () => {\n const props = {\n srcMediaId: '1',\n requestPlay: true,\n onEnded: () => {},\n };\n const { container } = render();\n expect(container.firstChild).toBe(null);\n });\n\n it('should render without crashing when onTogglePlay is defined', () => {\n const props = {\n srcMediaId: '1',\n requestPlay: true,\n onEnded: () => {},\n onTogglePlay: () => {},\n };\n const { container } = render();\n expect(container.firstChild).toBe(null);\n });\n\n it('should render without crashing when controls is defined', () => {\n const props = {\n srcMediaId: '1',\n requestPlay: true,\n onEnded: () => {},\n controls: true,\n };\n const { container } = render();\n expect(container.firstChild).toBe(null);\n });\n\n it('returns an error if srcMediaId is not 1', async () => {\n const props = {\n srcMediaId: '2',\n requestPlay: false,\n onEnded: () => {},\n };\n render();\n await waitFor(() => expect(mockMediaState.error).toBe('error'));\n });\n\n it('fetchMediaUrl sets url when srcMediaId is 1', async () => {\n const props = {\n srcMediaId: '1',\n requestPlay: false,\n onEnded: () => {},\n };\n render();\n await waitFor(() => expect(mockMediaState.id).toBe('abcd-1'));\n await waitFor(() => expect(mockMediaState.remoteId).toBe('1'));\n await waitFor(() => expect(mockMediaState.error).toBe(''));\n await waitFor(() => expect(mockMediaState.status).toBe(MediaSt.PENDING));\n await waitFor(() => expect(mockMediaState.status).toBe(MediaSt.FETCHED));\n await waitFor(() =>\n expect(mockMediaState.url).toBe('https://localhost/media/1.mp3')\n );\n });\n\n it('should render with an audio player with src', async () => {\n mockMediaState = {\n status: MediaSt.FETCHED,\n error: null,\n url: 'https://localhost/media/1.mp3',\n id: 'apcd-1',\n remoteId: '1',\n cancelled: false,\n };\n\n const props = {\n srcMediaId: '1',\n requestPlay: false,\n onEnded: () => {},\n };\n const { container } = render();\n await waitFor(() => expect(container.firstChild).not.toBe(null));\n expect(container.querySelector('audio')).toBeInTheDocument();\n expect(container.querySelector('audio')).toHaveAttribute(\n 'src',\n 'https://localhost/media/1.mp3'\n );\n expect(mockFetchBlob).not.toHaveBeenCalled();\n });\n\n it('should contain controls when controls parameter set', async () => {\n mockMediaState = {\n status: MediaSt.FETCHED,\n error: null,\n url: 'https://localhost/media/1.mp3',\n id: 'apcd-1',\n remoteId: '1',\n cancelled: false,\n };\n\n const props = {\n srcMediaId: '1',\n requestPlay: false,\n onEnded: () => {},\n controls: true,\n };\n const { container } = render();\n await waitFor(() => expect(container.firstChild).not.toBe(null));\n expect(container.querySelector('audio')).toHaveAttribute('controls');\n });\n\n it('should not call onTogglePlay without requestPlay', async () => {\n mockMediaState = {\n status: MediaSt.FETCHED,\n error: null,\n url: 'https://localhost/media/1.mp3',\n id: 'apcd-1',\n remoteId: '1',\n cancelled: false,\n };\n\n const props = {\n srcMediaId: '1',\n requestPlay: false,\n onEnded: () => {},\n onTogglePlay: jest.fn(),\n };\n const { container } = render();\n await waitFor(() => expect(container.firstChild).not.toBe(null));\n expect(container.querySelector('audio')).toBeInTheDocument();\n expect(props.onTogglePlay).not.toHaveBeenCalled();\n });\n\n it('should play with requestPlay true', async () => {\n mockMediaState = {\n status: MediaSt.FETCHED,\n error: null,\n url: 'https://localhost/media/1.mp3',\n id: 'apcd-1',\n remoteId: '1',\n cancelled: false,\n };\n\n const props = {\n srcMediaId: '1',\n requestPlay: true,\n onEnded: () => {},\n };\n\n const playStub = jest\n .spyOn(window.HTMLMediaElement.prototype, 'play')\n .mockImplementation(() => new Promise(() => {}));\n const { container } = render();\n await waitFor(() => expect(container.firstChild).not.toBe(null));\n expect(playStub).toHaveBeenCalled();\n playStub.mockRestore();\n });\n\n it('should call OnTogglePlay with pause event and requestPlay true', async () => {\n mockMediaState = {\n status: MediaSt.FETCHED,\n error: null,\n url: 'https://localhost/media/1.mp3',\n id: 'apcd-1',\n remoteId: '1',\n cancelled: false,\n };\n\n const props = {\n srcMediaId: '1',\n requestPlay: true,\n onEnded: () => {},\n onTogglePlay: jest.fn(),\n };\n\n const playStub = jest\n .spyOn(window.HTMLMediaElement.prototype, 'play')\n .mockImplementation(() => new Promise(() => {}));\n const { container } = render();\n await waitFor(() => expect(container.firstChild).not.toBe(null));\n container.querySelector('audio')?.dispatchEvent(new Event('pause'));\n expect(props.onTogglePlay).toHaveBeenCalled();\n expect(playStub).toHaveBeenCalled();\n playStub.mockRestore();\n });\n\n it('should call onEnded with ended event and requestPlay true', async () => {\n mockMediaState = {\n status: MediaSt.FETCHED,\n error: null,\n url: 'https://localhost/media/1.mp3',\n id: 'apcd-1',\n remoteId: '1',\n cancelled: false,\n };\n\n const props = {\n srcMediaId: '1',\n requestPlay: false,\n onEnded: jest.fn(),\n };\n\n const { container } = render();\n await waitFor(() => expect(container.firstChild).not.toBe(null));\n act(() => {\n container.querySelector('audio')?.dispatchEvent(new Event('ended'));\n });\n expect(props.onEnded).toHaveBeenCalled();\n });\n\n it('uses WaveSurfer proactively for unsupported formats', async () => {\n mockShouldUseWaveSurfer = true;\n mockMediaState = {\n status: MediaSt.FETCHED,\n error: null,\n url: 'https://localhost/media/1.ogg',\n id: 'abcd-ogg',\n remoteId: 'ogg-1',\n cancelled: false,\n };\n mockBlobState = {\n ...mockBlobClean,\n blobStat: BlobStatus.FETCHED,\n url: 'blob:mock',\n id: 'abcd-ogg',\n remoteId: 'ogg-1',\n blob: new Blob(['audio'], { type: 'audio/ogg' }),\n };\n\n const props = {\n srcMediaId: 'ogg-1',\n requestPlay: true,\n onEnded: () => {},\n };\n const { container } = render();\n await waitFor(() => expect(mockFetchBlob).toHaveBeenCalledWith('ogg-1'));\n await waitFor(() =>\n expect(container.querySelector('#hiddenplayer')).toBeInTheDocument()\n );\n expect(container.querySelector('audio')).not.toBeInTheDocument();\n });\n\n it('falls back to WaveSurfer when native audio errors', async () => {\n mockMediaState = {\n status: MediaSt.FETCHED,\n error: null,\n url: 'https://localhost/media/1.mp3',\n id: 'apcd-1',\n remoteId: '1',\n cancelled: false,\n };\n\n const props = {\n srcMediaId: '1',\n requestPlay: true,\n onEnded: jest.fn(),\n };\n const playStub = jest\n .spyOn(window.HTMLMediaElement.prototype, 'play')\n .mockImplementation(() => Promise.resolve());\n const { container } = render();\n await waitFor(() =>\n expect(container.querySelector('audio')).toBeInTheDocument()\n );\n\n act(() => {\n container.querySelector('audio')?.dispatchEvent(new Event('error'));\n });\n\n await waitFor(() => expect(mockFetchBlob).toHaveBeenCalledWith('1'));\n expect(mockShowMessage).not.toHaveBeenCalledWith('Media error');\n playStub.mockRestore();\n });\n\n it('shows mediaError when WaveSurfer blob fetch fails', async () => {\n mockShouldUseWaveSurfer = true;\n mockMediaState = {\n status: MediaSt.FETCHED,\n error: null,\n url: 'https://localhost/media/1.ogg',\n id: 'abcd-ogg',\n remoteId: 'ogg-1',\n cancelled: false,\n };\n mockBlobState = {\n ...mockBlobClean,\n blobStat: BlobStatus.ERROR,\n error: 'fetch failed abcd-ogg',\n id: 'abcd-ogg',\n remoteId: 'ogg-1',\n };\n\n const onEnded = jest.fn();\n render(\n \n );\n\n await waitFor(() =>\n expect(mockShowMessage).toHaveBeenCalledWith('Media error')\n );\n expect(onEnded).toHaveBeenCalled();\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\MediaPlayer.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'durationChangeNative', 'fetchMediaUrl', 'playItem', 'playbackMode', and 'stopPlay'. Either include them or remove the dependency array.","line":164,"column":6,"nodeType":"ArrayExpression","endLine":164,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [durationChangeNative, fetchMediaUrl, playItem, playbackMode, srcMediaId, stopPlay]","fix":{"range":[4962,4974],"text":"[durationChangeNative, fetchMediaUrl, playItem, playbackMode, srcMediaId, stopPlay]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getMediaContentType', 'onEnded', 'showMessage', 'switchToWaveSurfer', and 'ts.fileNotFound'. Either include them or remove the dependency array.","line":202,"column":6,"nodeType":"ArrayExpression","endLine":202,"endColumn":44,"suggestions":[{"desc":"Update the dependencies array to be: [getMediaContentType, mediaState, onEnded, playbackMode, showMessage, srcMediaId, switchToWaveSurfer, ts.fileNotFound]","fix":{"range":[6104,6142],"text":"[getMediaContentType, mediaState, onEnded, playbackMode, showMessage, srcMediaId, switchToWaveSurfer, ts.fileNotFound]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'onEnded', 'ready', 'showMessage', and 'ts.mediaError'. Either include them or remove the dependency array.","line":214,"column":6,"nodeType":"ArrayExpression","endLine":214,"endColumn":31,"suggestions":[{"desc":"Update the dependencies array to be: [blobState, onEnded, playbackMode, ready, showMessage, ts.mediaError]","fix":{"range":[6479,6504],"text":"[blobState, onEnded, playbackMode, ready, showMessage, ts.mediaError]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'stopPlay'. Either include it or remove the dependency array.","line":219,"column":6,"nodeType":"ArrayExpression","endLine":219,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [playItem, stopPlay]","fix":{"range":[6609,6619],"text":"[playItem, stopPlay]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'startPlayNative', 'startPlayWaveSurfer', and 'stopPlay'. Either include them or remove the dependency array.","line":234,"column":6,"nodeType":"ArrayExpression","endLine":234,"endColumn":59,"suggestions":[{"desc":"Update the dependencies array to be: [ready, requestPlay, playing, playItem, playbackMode, startPlayNative, stopPlay, startPlayWaveSurfer]","fix":{"range":[7097,7150],"text":"[ready, requestPlay, playing, playItem, playbackMode, startPlayNative, stopPlay, startPlayWaveSurfer]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\MediaRecord.load.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":2,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":2,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\MediaRecord.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":2,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":2,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\MediaRecord.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchMediaUrl' and 'mediaState.id'. Either include them or remove the dependency array.","line":422,"column":6,"nodeType":"ArrayExpression","endLine":422,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [fetchMediaUrl, mediaId, mediaState.id]","fix":{"range":[14920,14929],"text":"[fetchMediaUrl, mediaId, mediaState.id]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'trackState'. Either include it or remove the dependency array.","line":432,"column":6,"nodeType":"ArrayExpression","endLine":432,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [mediaState, trackState]","fix":{"range":[15248,15260],"text":"[mediaState, trackState]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setExtension'. Either include it or remove the dependency array.","line":455,"column":6,"nodeType":"ArrayExpression","endLine":455,"endColumn":35,"suggestions":[{"desc":"Update the dependencies array to be: [mimeType, extensions, mimes, setExtension]","fix":{"range":[15990,16019],"text":"[mimeType, extensions, mimes, setExtension]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setCanSave'. Either include it or remove the dependency array.","line":510,"column":6,"nodeType":"ArrayExpression","endLine":521,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [wantsSaveVisible, blobReady, processingRecording, tooBig, converting, uploading, recording, toolsChanged, waveformDuration, audioBlob, setCanSave]","fix":{"range":[17229,17409],"text":"[wantsSaveVisible, blobReady, processingRecording, tooBig, converting, uploading, recording, toolsChanged, waveformDuration, audioBlob, setCanSave]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'saveCompleted', 'setStatusText', and 't.saving'. Either include them or remove the dependency array.","line":568,"column":5,"nodeType":"ArrayExpression","endLine":568,"endColumn":56,"suggestions":[{"desc":"Update the dependencies array to be: [defaultFilename, onStageFile, setStatusText, t.saving, uploadMedia, saveCompleted, toolId]","fix":{"range":[19298,19349],"text":"[defaultFilename, onStageFile, setStatusText, t.saving, uploadMedia, saveCompleted, toolId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearRequested', 'compression', 'convertComplete', 'doUpload', 'filetype', 'handleSaveFailed', 'onReady', 'onSaveRejected', 'onSaving', 'reset', 'saveCompleted', 'saveRequested', 'setDoReset', 'setStatusText', 'showMessage', 'sizeLimit', 't.compressError', 't.compressing', 't.toobig', 't.toobigwarn', 'ts.NoSaveWoMedia', and 'waveformDuration'. Either include them or remove the dependency array.","line":664,"column":6,"nodeType":"ArrayExpression","endLine":664,"endColumn":70,"suggestions":[{"desc":"Update the dependencies array to be: [audioBlob, effectiveAudioBytes, toolsChanged, mimeType, toolId, sizeLimit, compression, t.toobig, t.toobigwarn, t.compressing, t.compressError, saveRequested, waveformDuration, onSaving, setStatusText, doUpload, filetype, handleSaveFailed, convertComplete, showMessage, onReady, onSaveRejected, ts.NoSaveWoMedia, saveCompleted, clearRequested, reset, setDoReset]","fix":{"range":[22503,22567],"text":"[audioBlob, effectiveAudioBytes, toolsChanged, mimeType, toolId, sizeLimit, compression, t.toobig, t.toobigwarn, t.compressing, t.compressError, saveRequested, waveformDuration, onSaving, setStatusText, doUpload, filetype, handleSaveFailed, convertComplete, showMessage, onReady, onSaveRejected, ts.NoSaveWoMedia, saveCompleted, clearRequested, reset, setDoReset]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'abandonLoadInFlight', 'reset', and 'setDoReset'. Either include them or remove the dependency array.","line":687,"column":6,"nodeType":"ArrayExpression","endLine":687,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [abandonLoadInFlight, doReset, reset, setDoReset]","fix":{"range":[23129,23138],"text":"[abandonLoadInFlight, doReset, reset, setDoReset]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'blobError' and 'stopLoading'. Either include them or remove the dependency array.","line":757,"column":5,"nodeType":"ArrayExpression","endLine":757,"endColumn":43,"suggestions":[{"desc":"Update the dependencies array to be: [blobError, ts.mediaError, stopLoading]","fix":{"range":[25280,25318],"text":"[blobError, ts.mediaError, stopLoading]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'handleLoadAudio' and 'loading'. Either include them or remove the dependency array.","line":846,"column":6,"nodeType":"ArrayExpression","endLine":846,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [handleLoadAudio, loading, preload]","fix":{"range":[28111,28120],"text":"[handleLoadAudio, loading, preload]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'abandonLoadInFlight', 'handleLoadAudio', 'loading', and 'reset'. Either include them or remove the dependency array.","line":860,"column":6,"nodeType":"ArrayExpression","endLine":860,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [abandonLoadInFlight, handleLoadAudio, loading, mediaId, reset]","fix":{"range":[28469,28478],"text":"[abandonLoadInFlight, handleLoadAudio, loading, mediaId, reset]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'handleLoadAudio'. Either include it or remove the dependency array.","line":873,"column":6,"nodeType":"ArrayExpression","endLine":873,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [handleLoadAudio, loading, mediaId]","fix":{"range":[29144,29162],"text":"[handleLoadAudio, loading, mediaId]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\MediaUpload.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\MediaUpload.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\MediaUploadContent.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has an unnecessary dependency: 'isUrl'. Either exclude it or remove the dependency array. Outer scope values like 'isUrl' aren't valid dependencies because mutating them doesn't re-render the component.","line":286,"column":5,"nodeType":"ArrayExpression","endLine":286,"endColumn":59,"suggestions":[{"desc":"Update the dependencies array to be: [ready, files, hasRights, uploadType, progress]","fix":{"range":[9128,9182],"text":"[ready, files, hasRights, uploadType, progress]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'onSaveDisabled'. Either include it or remove the dependency array.","line":292,"column":6,"nodeType":"ArrayExpression","endLine":292,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [onSaveDisabled, saveDisabled]","fix":{"range":[9310,9324],"text":"[onSaveDisabled, saveDisabled]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'controlsRef'. Either include it or remove the dependency array.","line":375,"column":6,"nodeType":"ArrayExpression","endLine":375,"endColumn":37,"suggestions":[{"desc":"Update the dependencies array to be: [controlsRef, handleAddOrSave, handleCancel]","fix":{"range":[11838,11869],"text":"[controlsRef, handleAddOrSave, handleCancel]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setFiles' and 'uploadType'. Either include them or remove the dependency array.","line":395,"column":6,"nodeType":"ArrayExpression","endLine":395,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [inValue, setFiles, uploadType]","fix":{"range":[12355,12364],"text":"[inValue, setFiles, uploadType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'checkSizes' and 'setFiles'. Either include them or remove the dependency array.","line":409,"column":6,"nodeType":"ArrayExpression","endLine":409,"endColumn":29,"suggestions":[{"desc":"Update the dependencies array to be: [uploadType, audioOnly, checkSizes, setFiles]","fix":{"range":[12860,12883],"text":"[uploadType, audioOnly, checkSizes, setFiles]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'initialFiles' and 'setFiles'. Either include them or remove the dependency array.","line":420,"column":6,"nodeType":"ArrayExpression","endLine":420,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [initialFiles, setFiles]","fix":{"range":[13332,13334],"text":"[initialFiles, setFiles]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ParatextLinked.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ParatextLinkedButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDataTable.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'findRef'. Either include it or remove the dependency array.","line":205,"column":6,"nodeType":"ArrayExpression","endLine":205,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [findRef, initFindRef]","fix":{"range":[5706,5719],"text":"[findRef, initFindRef]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'planType'. Either include it or remove the dependency array.","line":210,"column":5,"nodeType":"ArrayExpression","endLine":210,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [plan, planType]","fix":{"range":[5855,5861],"text":"[plan, planType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'checks'. Either include it or remove the dependency array.","line":228,"column":6,"nodeType":"ArrayExpression","endLine":228,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [value, data, checks]","fix":{"range":[6208,6221],"text":"[value, data, checks]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'onSelect'. Either include it or remove the dependency array.","line":344,"column":6,"nodeType":"ArrayExpression","endLine":344,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [checks, onSelect]","fix":{"range":[9467,9475],"text":"[checks, onSelect]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\ConsultantCheck.test.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,61],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport React from 'react';\nimport {\n cleanup,\n fireEvent,\n render,\n screen,\n waitFor,\n} from '@testing-library/react';\nimport ConsultantCheck from './ConsultantCheck';\nimport { SimpleWf } from '../../context/PassageDetailContext';\nimport { ArtifactTypeSlug } from '../../crud';\n\nlet mockWorkflow: SimpleWf[] = [];\nconst mockSetStepComplete = jest.fn();\nlet mockCurrentStep = '';\nlet mockCompare: string[] = [];\nlet mockPassageStepComplete: string | null = null;\nconst mockUpdateRecord = jest.fn();\n\n// Mock schema to avoid import.meta issues in Jest\nconst mockMemory = {\n cache: {\n query: jest.fn(() => []),\n },\n update: jest.fn(),\n};\n\njest.mock('../../schema', () => ({\n memory: mockMemory,\n requestedSchema: 100,\n}));\n\n// Mock GlobalContext to avoid context errors\njest.mock('../../context/useGlobal', () => ({\n useGlobal: jest.fn((key: string) => {\n const mockValues: Record = {\n memory: mockMemory,\n remoteBusy: false,\n };\n return [mockValues[key], jest.fn()];\n }),\n useGetGlobal: jest.fn(() =>\n jest.fn((key: string) => {\n const mockValues: Record = {\n memory: mockMemory,\n remoteBusy: false,\n };\n return mockValues[key];\n })\n ),\n}));\n\n// Mock GlobalContext\njest.mock('../../context/GlobalContext', () => ({\n GlobalContext: React.createContext({\n globalState: {},\n setGlobalState: jest.fn(),\n }),\n}));\n\njest.mock('../../utils/useStepPermission', () => ({\n useStepPermissions: () => ({\n canDoSectionStep: jest.fn(() => true),\n }),\n}));\njest.mock('../../crud', () => ({\n useArtifactType: () => ({\n localizedArtifactType: (slug: ArtifactTypeSlug) => {\n if (slug === 'vernacular') return 'Vernacular';\n else if (slug === 'backtranslation') return 'Phrase Back Translation';\n else return 'other';\n },\n }),\n findRecord: (memory: any, table: any, id: string) => {\n if (table === 'passage')\n return { attributes: { stepComplete: mockPassageStepComplete } };\n if (id === '1') return { attributes: { tool: '{\"tool\": \"record\"}' } };\n else if (id === '2')\n return { attributes: { tool: '{\"tool\": \"phraseBackTranslate\"}' } };\n },\n useOrgDefaults: () => ({\n getOrgDefault: () => {\n return mockCompare;\n },\n setOrgDefault: jest.fn(),\n }),\n useUpdateRecord: () => mockUpdateRecord,\n ArtifactTypeSlug: jest.requireActual('../../crud/artifactTypeSlug')\n .ArtifactTypeSlug,\n ToolSlug: jest.requireActual('../../crud/toolSlug').ToolSlug,\n}));\njest.mock('../../context/usePassageDetailContext', () => () => ({\n workflow: mockWorkflow,\n stepComplete: () => false,\n setStepComplete: mockSetStepComplete,\n gotoNextStep: jest.fn(),\n currentstep: mockCurrentStep,\n passage: { id: 'p1', attributes: { stepComplete: mockPassageStepComplete } },\n section: { id: 's1' },\n sharedResource: undefined,\n}));\njest.mock('../MediaPlayer', () => {\n const MockMediaPlayer = () =>
MediaPlayer
;\n MockMediaPlayer.displayName = 'MockMediaPlayer';\n return MockMediaPlayer;\n});\njest.mock('./ConsultantCheckReview', () => {\n const MockConsultantCheckReview = ({ item }: { item: string }) => (\n <>\n
ConsultantCheckReview
\n
{item}
\n \n );\n MockConsultantCheckReview.displayName = 'MockConsultantCheckReview';\n return MockConsultantCheckReview;\n});\njest.mock('../../control', () => ({\n ActionRow: jest.requireActual('../../control/ActionRow').ActionRow,\n Button: jest.requireActual('../../control/Button').Button,\n GrowingDiv: jest.requireActual('../../control/GrowingDiv').GrowingDiv,\n}));\njest.mock('../../selector', () => ({\n consultantSelector: jest.fn(),\n sharedSelector: jest.fn(),\n}));\njest.mock('react-redux', () => ({\n useSelector: () => ({\n furtherReview: 'Further Review',\n approved: 'Approved',\n wait: 'Please wait.',\n }),\n shallowEqual: jest.fn(),\n}));\njest.mock('../../hoc/BigDialog', () => {\n const MockBigDialog = (props: any) => (\n <>\n
BigDialog
\n
{props.isOpen ? 'compare-open' : 'compare-close'}
\n
{props.children}
\n \n );\n MockBigDialog.displayName = 'MockBigDialog';\n return MockBigDialog;\n});\njest.mock('./ConsultantCheckCompare', () => {\n const MockConsultantCheckCompare = (props: any) => (\n <>\n
ConsultantCheckCompare
\n
{JSON.stringify(props, null, 2)}
\n \n );\n MockConsultantCheckCompare.displayName = 'MockConsultantCheckCompare';\n return MockConsultantCheckCompare;\n});\njest.mock('../../model/baseModel', () => ({\n UpdateRecord: jest.fn(),\n}));\njest.mock('@orbit/records', () => ({\n RecordTransformBuilder: jest.fn(),\n}));\njest.mock('../../hoc/SnackBar', () => ({\n useSnackBar: () => ({\n showMessage: (message: string) =>
{message}
,\n }),\n}));\n\ndescribe('ConsultantCheck', () => {\n beforeEach(cleanup);\n afterEach(() => {\n mockWorkflow = [];\n mockCurrentStep = '';\n mockCompare = [];\n mockPassageStepComplete = null;\n mockSetStepComplete.mockClear();\n mockUpdateRecord.mockClear();\n });\n\n it('should render', () => {\n const { container } = render();\n expect(container).not.toBe(null);\n });\n\n it('should render ConsultantCheckReview', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n ];\n render();\n expect(screen.getByText('ConsultantCheckReview')).not.toBe(null);\n expect(screen.getByText('vernacular')).not.toBe(null);\n });\n\n it('should render Vernacular tab', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n ];\n render();\n expect(screen.getByText('Vernacular')).not.toBe(null);\n });\n\n it('should render ActionRow', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n ];\n render();\n expect(screen.getByTestId('action-row')).not.toBe(null);\n });\n\n it('should render the approve button', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n ];\n render();\n expect(screen.getByTestId('pri-button')).not.toBe(null);\n });\n\n it('should render the further review button when approve is clicked', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n ];\n render();\n fireEvent.click(screen.getByTestId('pri-button'));\n expect(screen.getByTestId('alt-button')).not.toBe(null);\n expect(screen.queryAllByTestId('pri-button')).toHaveLength(0);\n });\n\n it('should render remain selected when its the only tab and approve is clicked', async () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n ];\n mockCurrentStep = 'record';\n render();\n fireEvent.click(screen.getByTestId('pri-button'));\n expect(screen.getByText('Vernacular')).toHaveClass('Mui-selected');\n await waitFor(() => expect(mockSetStepComplete).toHaveBeenCalledTimes(1));\n expect(mockSetStepComplete).toHaveBeenCalledWith('record', true);\n });\n\n it('should update passage record and include completed when approve is clicked', async () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n ];\n mockCurrentStep = 'record';\n render();\n fireEvent.click(screen.getByTestId('pri-button'));\n await waitFor(() => expect(mockSetStepComplete).toHaveBeenCalledTimes(1));\n expect(mockSetStepComplete).toHaveBeenCalledWith('record', true);\n expect(mockUpdateRecord).toHaveBeenCalledTimes(1);\n const stepCompleteJson =\n mockUpdateRecord['mock'].calls[0][0]?.attributes?.stepComplete;\n const result = JSON.parse(stepCompleteJson);\n expect(result.completed).toEqual([]);\n });\n\n it('should update passage record and keep completed when approve is clicked', async () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n ];\n mockCurrentStep = 'record';\n mockPassageStepComplete = `{\"completed\":[\"record\"]}`;\n render();\n fireEvent.click(screen.getByTestId('pri-button'));\n await waitFor(() => expect(mockSetStepComplete).toHaveBeenCalledTimes(1));\n expect(mockSetStepComplete).toHaveBeenCalledWith('record', true);\n expect(mockUpdateRecord).toHaveBeenCalledTimes(1);\n const stepCompleteJson =\n mockUpdateRecord['mock'].calls[0][0]?.attributes?.stepComplete;\n const result = JSON.parse(stepCompleteJson);\n expect(result.completed).toEqual(['record']);\n });\n\n it('should have a second tab when workflow has the right two items', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n {\n id: '2',\n label: 'Phrase Back Translation',\n },\n ];\n render();\n expect(screen.getByText('Vernacular')).not.toBe(null);\n expect(screen.getByText('Phrase Back Translation')).not.toBe(null);\n });\n\n it('should have selected PBT when it has two items', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n {\n id: '2',\n label: 'Phrase Back Translation',\n },\n ];\n render();\n expect(screen.getByText('Phrase Back Translation')).not.toBe(null);\n expect(screen.getByText('Phrase Back Translation')).toHaveClass(\n 'Mui-selected'\n );\n });\n\n it('should select Vernacular when the primary button is clicked', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n {\n id: '2',\n label: 'Phrase Back Translation',\n },\n ];\n render();\n fireEvent.click(screen.getByTestId('pri-button'));\n expect(screen.getByText('Vernacular')).not.toBe(null);\n expect(screen.getByText('Vernacular')).toHaveClass('Mui-selected');\n });\n\n it('should open the compare dialog when compare button clicked', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n {\n id: '2',\n label: 'Phrase Back Translation',\n },\n ];\n render();\n expect(screen.getByText('compare-close')).toBeInTheDocument();\n fireEvent.click(screen.getByTestId('compare-button'));\n expect(screen.getByText('compare-open')).toBeInTheDocument();\n });\n\n it('should not have a compare button with one artifact type', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n ];\n render();\n expect(screen.queryAllByTestId('compare-button')).toHaveLength(0);\n });\n\n it('should render a table if compare set', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n {\n id: '2',\n label: 'Phrase Back Translation',\n },\n ];\n mockCompare = ['1', '2'];\n const { container } = render();\n expect(container.querySelector('table')).toBeInTheDocument();\n });\n\n it('should only include each artifact type once in the list of tabs', () => {\n mockWorkflow = [\n {\n id: '1',\n label: 'Record',\n },\n {\n id: '2',\n label: 'Phrase Back Translation',\n },\n {\n id: '3',\n label: 'Phrase Back Translation',\n },\n ];\n render();\n expect(screen.queryAllByText('Phrase Back Translation')).toHaveLength(1);\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\ConsultantCheck.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getOrgDefault', 'memory', and 'passage?.id'. Either include them or remove the dependency array.","line":239,"column":6,"nodeType":"ArrayExpression","endLine":239,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, memory, passage?.id, workflow]","fix":{"range":[7365,7375],"text":"[getOrgDefault, memory, passage?.id, workflow]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\ConsultantCheckCompare.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":2,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":2,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\ConsultantCheckCompare.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\ConsultantCheckReview.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":2,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":2,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\ConsultantCheckReview.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'onPlayer'. Either include it or remove the dependency array. If 'onPlayer' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":184,"column":6,"nodeType":"ArrayExpression","endLine":191,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [item, selectedLang, rowData, mediafileId, artifactType, langOptions.length, onPlayer]","fix":{"range":[6016,6121],"text":"[item, selectedLang, rowData, mediafileId, artifactType, langOptions.length, onPlayer]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\AddResource.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\AddResourceAction.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\CreateAiRes.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'aiQueries' and 'scopeOptions'. Either include them or remove the dependency array.","line":129,"column":6,"nodeType":"ArrayExpression","endLine":129,"endColumn":22,"suggestions":[{"desc":"Update the dependencies array to be: [t, organizedBy, aiQueries, scopeOptions]","fix":{"range":[3990,4006],"text":"[t, organizedBy, aiQueries, scopeOptions]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'computeQuery' and 'computeTerms'. Either include them or remove the dependency array.","line":189,"column":6,"nodeType":"ArrayExpression","endLine":189,"endColumn":53,"suggestions":[{"desc":"Update the dependencies array to be: [passage, scope, type, allBookData, userEdited, computeQuery, computeTerms]","fix":{"range":[6100,6147],"text":"[passage, scope, type, allBookData, userEdited, computeQuery, computeTerms]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\DoneButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\FaithbridgeIframe.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has a missing dependency: 'memory.keyMap'. Either include it or remove the dependency array.","line":79,"column":5,"nodeType":"ArrayExpression","endLine":79,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [memory.keyMap, userId]","fix":{"range":[3495,3503],"text":"[memory.keyMap, userId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'checkOnline'. Either include it or remove the dependency array.","line":95,"column":6,"nodeType":"ArrayExpression","endLine":95,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [checkOnline]","fix":{"range":[3851,3853],"text":"[checkOnline]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'ts.mustBeOnline'. Either include it or remove the dependency array.","line":111,"column":6,"nodeType":"ArrayExpression","endLine":111,"endColumn":17,"suggestions":[{"desc":"Update the dependencies array to be: [connected, ts.mustBeOnline]","fix":{"range":[4234,4245],"text":"[connected, ts.mustBeOnline]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'passageRef'. Either include it or remove the dependency array.","line":116,"column":6,"nodeType":"ArrayExpression","endLine":116,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [passage, passageRef]","fix":{"range":[4378,4387],"text":"[passage, passageRef]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'userRemoteId'. Either include it or remove the dependency array.","line":128,"column":6,"nodeType":"ArrayExpression","endLine":128,"endColumn":30,"suggestions":[{"desc":"Update the dependencies array to be: [chat, verseRef, userId, userRemoteId]","fix":{"range":[4706,4730],"text":"[chat, verseRef, userId, userRemoteId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'onClose', 'onMarkdown', 'showMessage', 't.updating', and 't.video'. Either include them or remove the dependency array. If 'onMarkdown' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":191,"column":6,"nodeType":"ArrayExpression","endLine":191,"endColumn":26,"suggestions":[{"desc":"Update the dependencies array to be: [data, audio, token, showMessage, t.updating, t.video, onMarkdown, onClose]","fix":{"range":[6940,6960],"text":"[data, audio, token, showMessage, t.updating, t.video, onMarkdown, onClose]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'errorReporter', 'refresh', 'showMessage', and 't.noInfo'. Either include them or remove the dependency array. You can also do a functional update 'setRefresh(r => ...)' if you only need 'refresh' in the 'setRefresh' call.","line":206,"column":6,"nodeType":"ArrayExpression","endLine":206,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [error, errorReporter, refresh, showMessage, t.noInfo]","fix":{"range":[7411,7418],"text":"[error, errorReporter, refresh, showMessage, t.noInfo]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\FindAquifer.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'curNoteRef', 'limit', 'query', and 'token'. Either include them or remove the dependency array.","line":407,"column":6,"nodeType":"ArrayExpression","endLine":407,"endColumn":38,"suggestions":[{"desc":"Update the dependencies array to be: [passage, lang, refresh, offset, limit, query, token, curNoteRef]","fix":{"range":[11751,11783],"text":"[passage, lang, refresh, offset, limit, query, token, curNoteRef]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\FindBibleBrain.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'planType'. Either include it or remove the dependency array.","line":125,"column":54,"nodeType":"ArrayExpression","endLine":125,"endColumn":60,"suggestions":[{"desc":"Update the dependencies array to be: [plan, planType]","fix":{"range":[4688,4694],"text":"[plan, planType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'Nt', 'Ot', 'getBibles', 'languages', and 'timing'. Either include them or remove the dependency array.","line":153,"column":6,"nodeType":"ArrayExpression","endLine":153,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [Nt, Ot, getBibles, lang, languages, timing]","fix":{"range":[5538,5544],"text":"[Nt, Ot, getBibles, lang, languages, timing]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'token'. Either include it or remove the dependency array.","line":182,"column":6,"nodeType":"ArrayExpression","endLine":182,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [bibleOpt, Nt, timing, token]","fix":{"range":[6344,6366],"text":"[bibleOpt, Nt, timing, token]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'bookN' and 'getLanguages'. Either include them or remove the dependency array.","line":194,"column":6,"nodeType":"ArrayExpression","endLine":194,"endColumn":23,"suggestions":[{"desc":"Update the dependencies array to be: [timing, passage, bookN, getLanguages]","fix":{"range":[6750,6767],"text":"[timing, passage, bookN, getLanguages]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\FindOther.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\FindTabs.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\GeneralResourceDeleteDialog.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\GeneralResourceDeleteDialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\PassageDetailArtifacts.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\PassageDetailArtifacts.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'artifactState'. Either include it or remove the dependency array.","line":292,"column":6,"nodeType":"ArrayExpression","endLine":292,"endColumn":34,"suggestions":[{"desc":"Update the dependencies array to be: [artifactState, artifactTypes, offlineOnly]","fix":{"range":[12238,12266],"text":"[artifactState, artifactTypes, offlineOnly]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 't.noteResource' and 't.passageResource'. Either include them or remove the dependency array.","line":785,"column":5,"nodeType":"ArrayExpression","endLine":785,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [passage?.attributes?.reference, t.noteResource, t.passageResource]","fix":{"range":[28688,28697],"text":"[passage?.attributes?.reference, t.noteResource, t.passageResource]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'getOrganizedBy', 'getSectionType', 't.bookResource', and 't.movementResource'. Either include them or remove the dependency array.","line":803,"column":5,"nodeType":"ArrayExpression","endLine":803,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [getOrganizedBy, getSectionType, t.bookResource, t.movementResource]","fix":{"range":[29210,29219],"text":"[getOrganizedBy, getSectionType, t.bookResource, t.movementResource]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'listFilter'. Either include it or remove the dependency array.","line":820,"column":6,"nodeType":"ArrayExpression","endLine":820,"endColumn":47,"suggestions":[{"desc":"Update the dependencies array to be: [rowData, allResources, busy, remoteBusy, listFilter]","fix":{"range":[29669,29710],"text":"[rowData, allResources, busy, remoteBusy, listFilter]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":974,"column":6,"nodeType":"ArrayExpression","endLine":974,"endColumn":33,"suggestions":[{"desc":"Update the dependencies array to be: [sectionResources, memory, rowData]","fix":{"range":[35388,35415],"text":"[sectionResources, memory, rowData]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getArtifactCategorys'. Either include it or remove the dependency array.","line":981,"column":6,"nodeType":"ArrayExpression","endLine":981,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [getArtifactCategorys]","fix":{"range":[35613,35615],"text":"[getArtifactCategorys]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'projResSetup'. Either include it or remove the dependency array. You can also do a functional update 'setProjResSetup(p => ...)' if you only need 'projResSetup' in the 'setProjResSetup' call.","line":1107,"column":6,"nodeType":"ArrayExpression","endLine":1107,"endColumn":48,"suggestions":[{"desc":"Update the dependencies array to be: [projResPassageVisible, projResSetup, projResWizVisible]","fix":{"range":[40557,40599],"text":"[projResPassageVisible, projResSetup, projResWizVisible]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'handleSelectProjectResource'. Either include it or remove the dependency array.","line":1125,"column":6,"nodeType":"ArrayExpression","endLine":1125,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [handleSelectProjectResource, projResSetup]","fix":{"range":[41358,41372],"text":"[handleSelectProjectResource, projResSetup]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'planType'. Either include it or remove the dependency array.","line":1211,"column":5,"nodeType":"ArrayExpression","endLine":1211,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [plan, planType]","fix":{"range":[44087,44093],"text":"[plan, planType]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\PassageDetailsArtifactsMobile.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'artifactState'. Either include it or remove the dependency array.","line":291,"column":6,"nodeType":"ArrayExpression","endLine":291,"endColumn":34,"suggestions":[{"desc":"Update the dependencies array to be: [artifactState, artifactTypes, offlineOnly]","fix":{"range":[12792,12820],"text":"[artifactState, artifactTypes, offlineOnly]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 't.noteResource' and 't.passageResource'. Either include them or remove the dependency array.","line":786,"column":5,"nodeType":"ArrayExpression","endLine":786,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [passage?.attributes?.reference, t.noteResource, t.passageResource]","fix":{"range":[29253,29262],"text":"[passage?.attributes?.reference, t.noteResource, t.passageResource]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'getOrganizedBy', 'getSectionType', 't.bookResource', and 't.movementResource'. Either include them or remove the dependency array.","line":804,"column":5,"nodeType":"ArrayExpression","endLine":804,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [getOrganizedBy, getSectionType, t.bookResource, t.movementResource]","fix":{"range":[29775,29784],"text":"[getOrganizedBy, getSectionType, t.bookResource, t.movementResource]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'listFilter'. Either include it or remove the dependency array.","line":821,"column":6,"nodeType":"ArrayExpression","endLine":821,"endColumn":47,"suggestions":[{"desc":"Update the dependencies array to be: [rowData, allResources, busy, remoteBusy, listFilter]","fix":{"range":[30234,30275],"text":"[rowData, allResources, busy, remoteBusy, listFilter]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":965,"column":6,"nodeType":"ArrayExpression","endLine":965,"endColumn":33,"suggestions":[{"desc":"Update the dependencies array to be: [sectionResources, memory, rowData]","fix":{"range":[35609,35636],"text":"[sectionResources, memory, rowData]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getArtifactCategorys'. Either include it or remove the dependency array.","line":972,"column":6,"nodeType":"ArrayExpression","endLine":972,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [getArtifactCategorys]","fix":{"range":[35834,35836],"text":"[getArtifactCategorys]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'projResSetup'. Either include it or remove the dependency array. You can also do a functional update 'setProjResSetup(p => ...)' if you only need 'projResSetup' in the 'setProjResSetup' call.","line":1098,"column":6,"nodeType":"ArrayExpression","endLine":1098,"endColumn":48,"suggestions":[{"desc":"Update the dependencies array to be: [projResPassageVisible, projResSetup, projResWizVisible]","fix":{"range":[40778,40820],"text":"[projResPassageVisible, projResSetup, projResWizVisible]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'handleSelectProjectResource'. Either include it or remove the dependency array.","line":1116,"column":6,"nodeType":"ArrayExpression","endLine":1116,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [handleSelectProjectResource, projResSetup]","fix":{"range":[41579,41593],"text":"[handleSelectProjectResource, projResSetup]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'planType'. Either include it or remove the dependency array.","line":1196,"column":5,"nodeType":"ArrayExpression","endLine":1196,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [plan, planType]","fix":{"range":[44168,44174],"text":"[plan, planType]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\PassageResourceButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\PlayButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\ProjectResourceConfigure.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'ColName.Ref', 'emptyTable', 'fullReference', 'handleSegment', 'memory', and 'rowCells'. Either include them or remove the dependency array.","line":337,"column":6,"nodeType":"ArrayExpression","endLine":337,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [ColName.Ref, emptyTable, fullReference, handleSegment, items, memory, rowCells]","fix":{"range":[12496,12503],"text":"[ColName.Ref, emptyTable, fullReference, handleSegment, items, memory, rowCells]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearCompleted', 'clearRequested', 'saveRequested', and 'writeResources'. Either include them or remove the dependency array.","line":418,"column":6,"nodeType":"ArrayExpression","endLine":418,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [clearCompleted, clearRequested, saveRequested, toolsChanged, writeResources]","fix":{"range":[14911,14925],"text":"[clearCompleted, clearRequested, saveRequested, toolsChanged, writeResources]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'toolChanged'. Either include it or remove the dependency array.","line":428,"column":6,"nodeType":"ArrayExpression","endLine":428,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [toolChanged]","fix":{"range":[15433,15435],"text":"[toolChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'ColName.Limits' and 'ColName.Ref'. Either include them or remove the dependency array.","line":654,"column":5,"nodeType":"ArrayExpression","endLine":654,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [ColName.Limits, ColName.Ref, data]","fix":{"range":[22624,22630],"text":"[ColName.Limits, ColName.Ref, data]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\ResourceData.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\ResourceEditAction.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\ResourceItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\ResourceTypeEnum.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\SelectMyResource.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":38,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":38,"endColumn":13,"suppressions":[{"kind":"directive","justification":"JSX (react-jsx) still expects React in scope for TS in this file"}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\SelectMyResource.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'myWidth'. Either include it or remove the dependency array.","line":51,"column":6,"nodeType":"ArrayExpression","endLine":51,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [myWidth]","fix":{"range":[1752,1754],"text":"[myWidth]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\SelectSections.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":128,"column":5,"nodeType":"ArrayExpression","endLine":128,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [memory, plan]","fix":{"range":[4376,4382],"text":"[memory, plan]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'planType'. Either include it or remove the dependency array.","line":134,"column":6,"nodeType":"ArrayExpression","endLine":134,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [plan, planType]","fix":{"range":[4520,4526],"text":"[plan, planType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getOrganizedBy' and 'planRec?.id'. Either include them or remove the dependency array.","line":148,"column":6,"nodeType":"ArrayExpression","endLine":148,"endColumn":53,"suggestions":[{"desc":"Update the dependencies array to be: [plan, passages, sections, allBookData, isFlat, planRec?.id, getOrganizedBy]","fix":{"range":[4847,4894],"text":"[plan, passages, sections, allBookData, isFlat, planRec?.id, getOrganizedBy]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\SelectSharedResource.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'planType'. Either include it or remove the dependency array.","line":65,"column":6,"nodeType":"ArrayExpression","endLine":65,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [plan, planType]","fix":{"range":[2398,2404],"text":"[plan, planType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'bookSuggestions', 'isFlat', 'memory', and 'planType'. Either include them or remove the dependency array.","line":109,"column":6,"nodeType":"ArrayExpression","endLine":109,"endColumn":31,"suggestions":[{"desc":"Update the dependencies array to be: [passage, section, scope, planType, bookSuggestions, memory, isFlat]","fix":{"range":[3771,3796],"text":"[passage, section, scope, planType, bookSuggestions, memory, isFlat]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'memory.cache' and 'memory?.keyMap'. Either include them or remove the dependency array.","line":164,"column":5,"nodeType":"ArrayExpression","endLine":164,"endColumn":22,"suggestions":[{"desc":"Update the dependencies array to be: [bookCd, findRef, memory.cache, memory?.keyMap]","fix":{"range":[5646,5663],"text":"[bookCd, findRef, memory.cache, memory?.keyMap]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getAllSharedResources'. Either include it or remove the dependency array.","line":184,"column":6,"nodeType":"ArrayExpression","endLine":184,"endColumn":40,"suggestions":[{"desc":"Update the dependencies array to be: [sourcePassages, refLevel, refRes, getAllSharedResources]","fix":{"range":[6356,6390],"text":"[sourcePassages, refLevel, refRes, getAllSharedResources]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'localizedArtifactCategory', 't.no', and 't.yes'. Either include them or remove the dependency array.","line":212,"column":6,"nodeType":"ArrayExpression","endLine":212,"endColumn":17,"suggestions":[{"desc":"Update the dependencies array to be: [localizedArtifactCategory, resources, t.no, t.yes]","fix":{"range":[7383,7394],"text":"[localizedArtifactCategory, resources, t.no, t.yes]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\SortableHeader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\SortableItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\TableRow.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\UploadRecordToggle.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\ViewButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\addLinkKind.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\buildResourcePendingRestore.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\buildResourcePendingRestore.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\buildSelectSectionRows.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\buildSelectSectionRows.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\generalResourceMedia.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\generalResourceMedia.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\getResources.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\internalizeLabels.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\mobile components\\AudioResourceCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\mobile components\\TextResourceCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\projectResourceAssignments.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\projectResourceAssignments.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\resourceArtifactName.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\resourceArtifactName.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\resourceRows.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\scopeI.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\useComputeRef.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\useFaithbridgeResult.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\useFullReference.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\usePassageRef.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\useProjectResourceSave.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'getTypeId'. Either include it or remove the dependency array.","line":54,"column":5,"nodeType":"ArrayExpression","endLine":54,"endColumn":7,"suggestions":[{"desc":"Update the dependencies array to be: [getTypeId]","fix":{"range":[1275,1277],"text":"[getTypeId]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\useProjectSegmentSave.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\useProjectSegmentSave.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Internalization\\useResumePendingProjectResourceConfig.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'isAddingAudioResourceRef', 'memory', and 'setProjResSetup'. Either include them or remove the dependency array. If 'setProjResSetup' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":42,"column":6,"nodeType":"ArrayExpression","endLine":42,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [isAddingAudioResourceRef, mediafiles, memory, setProjResSetup]","fix":{"range":[1383,1395],"text":"[isAddingAudioResourceRef, mediafiles, memory, setProjResSetup]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\KeyTermChip.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\KeyTermDetail.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\KeyTermExclude.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'cat' and 'getLabel'. Either include them or remove the dependency array. If 'getLabel' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":64,"column":6,"nodeType":"ArrayExpression","endLine":64,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [cat, getLabel, init]","fix":{"range":[1995,2001],"text":"[cat, getLabel, init]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\KeyTermSetting.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\KeyTermSort.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\KeyTermTable.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'saveKeyTermTarget'. Either include it or remove the dependency array.","line":136,"column":5,"nodeType":"ArrayExpression","endLine":136,"endColumn":17,"suggestions":[{"desc":"Update the dependencies array to be: [saveKeyTermTarget, targetText]","fix":{"range":[4669,4681],"text":"[saveKeyTermTarget, targetText]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\KeyTermVisible.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\KeyTerms.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getOrgDefault', 'initExcluded', 'setLocale', and 'setSortBy'. Either include them or remove the dependency array.","line":120,"column":6,"nodeType":"ArrayExpression","endLine":120,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, initExcluded, setLocale, setSortBy]","fix":{"range":[3596,3614],"text":"[getOrgDefault, initExcluded, setLocale, setSortBy]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked.","line":120,"column":7,"nodeType":"LogicalExpression","endLine":120,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\TargetWordAdd.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setCommentRecording'. Either include it or remove the dependency array.","line":186,"column":6,"nodeType":"ArrayExpression","endLine":186,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [setCommentRecording]","fix":{"range":[4884,4886],"text":"[setCommentRecording]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearRequested', 'handleCancel', 'handleOk', 'saveRequested', and 'toolId'. Either include them or remove the dependency array.","line":197,"column":6,"nodeType":"ArrayExpression","endLine":197,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [clearRequested, handleCancel, handleOk, saveRequested, toolId, toolsChanged]","fix":{"range":[5186,5200],"text":"[clearRequested, handleCancel, handleOk, saveRequested, toolId, toolsChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'reset'. Either include it or remove the dependency array.","line":221,"column":6,"nodeType":"ArrayExpression","endLine":221,"endColumn":25,"suggestions":[{"desc":"Update the dependencies array to be: [reset, row.target.length]","fix":{"range":[5781,5800],"text":"[reset, row.target.length]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\keyTermPendingRestore.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\keyTermPendingRestore.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Keyterms\\useKeyTerms.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'defaultLabels' and 'ktCat'. Either include them or remove the dependency array.","line":87,"column":6,"nodeType":"ArrayExpression","endLine":87,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [defaultLabels, ktCat, language]","fix":{"range":[2837,2847],"text":"[defaultLabels, ktCat, language]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailCarefulSpeech.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailCarefulSpeech.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailChooser.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'chooserSize', 'getSharedResource', 'memory', 'passageCount', and 'setChooserSize'. Either include them or remove the dependency array.","line":129,"column":6,"nodeType":"ArrayExpression","endLine":129,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [section, allBookData, memory, passageCount, chooserSize, setChooserSize, getSharedResource]","fix":{"range":[4145,4167],"text":"[section, allBookData, memory, passageCount, chooserSize, setChooserSize, getSharedResource]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'value'. Either include it or remove the dependency array.","line":136,"column":6,"nodeType":"ArrayExpression","endLine":136,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [passage, value]","fix":{"range":[4421,4430],"text":"[passage, value]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'passageNavigate'. Either include it or remove the dependency array.","line":141,"column":6,"nodeType":"ArrayExpression","endLine":141,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [passageNavigate, view]","fix":{"range":[4546,4552],"text":"[passageNavigate, view]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailDiscuss.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'currentStep'. Either include it or remove the dependency array.","line":26,"column":6,"nodeType":"ArrayExpression","endLine":26,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [currentStep, orgSteps]","fix":{"range":[1004,1014],"text":"[currentStep, orgSteps]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailGrids.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'planType'. Either include it or remove the dependency array.","line":114,"column":5,"nodeType":"ArrayExpression","endLine":114,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [plan, planType]","fix":{"range":[4102,4108],"text":"[plan, planType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'memory.cache'. Either include it or remove the dependency array.","line":161,"column":6,"nodeType":"ArrayExpression","endLine":161,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [memory.cache, plan]","fix":{"range":[5599,5605],"text":"[memory.cache, plan]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailGuidedPhraseRecord.nextDuringPlayback.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailGuidedPhraseRecord.stepScope.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailGuidedPhraseRecord.tsx","messages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has an unnecessary dependency: 'clauseSegString'. Either exclude it or remove the dependency array.","line":1229,"column":5,"nodeType":"ArrayExpression","endLine":1238,"endColumn":6,"suggestions":[{"desc":"Update the dependencies array to be: [setClauseSeg, persistClauseSegments, phraseSegParams, applyColors, clauseRegions, recordedClauseIndicesForTools, pushSegmentUndo]","fix":{"range":[44034,44236],"text":"[setClauseSeg, persistClauseSegments, phraseSegParams, applyColors, clauseRegions, recordedClauseIndicesForTools, pushSegmentUndo]"}}]}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has an unnecessary dependency: 'optimisticVersion'. Either exclude it or remove the dependency array.","line":538,"column":6,"nodeType":"ArrayExpression","endLine":538,"endColumn":40,"suggestions":[{"desc":"Update the dependencies array to be: [clauseRegions]","fix":{"range":[19137,19171],"text":"[clauseRegions]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setStepComplete', 'stepComplete', and 'waitForSave'. Either include them or remove the dependency array.","line":609,"column":6,"nodeType":"ArrayExpression","endLine":609,"endColumn":75,"suggestions":[{"desc":"Update the dependencies array to be: [allClausesComplete, bootstrapped, clauseRegions.length, currentstep, setStepComplete, stepComplete, waitForSave]","fix":{"range":[22319,22388],"text":"[allClausesComplete, bootstrapped, clauseRegions.length, currentstep, setStepComplete, stepComplete, waitForSave]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setPlaying'. Either include it or remove the dependency array.","line":732,"column":6,"nodeType":"ArrayExpression","endLine":732,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [mediafileId, setPlaying]","fix":{"range":[25887,25900],"text":"[mediafileId, setPlaying]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getCurrentSegment' and 'setCurrentSegment'. Either include them or remove the dependency array.","line":775,"column":6,"nodeType":"ArrayExpression","endLine":775,"endColumn":35,"suggestions":[{"desc":"Update the dependencies array to be: [currentRegion, currentIndex, getCurrentSegment, setCurrentSegment]","fix":{"range":[26955,26984],"text":"[currentRegion, currentIndex, getCurrentSegment, setCurrentSegment]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'startSave' and 'toolId'. Either include them or remove the dependency array.","line":793,"column":6,"nodeType":"ArrayExpression","endLine":793,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [canSave, startSave, toolId]","fix":{"range":[27778,27787],"text":"[canSave, startSave, toolId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'startSave'. Either include it or remove the dependency array.","line":804,"column":6,"nodeType":"ArrayExpression","endLine":804,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [startSave, toolId]","fix":{"range":[28184,28192],"text":"[startSave, toolId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'latchRecordingTarget'. Either include it or remove the dependency array.","line":819,"column":6,"nodeType":"ArrayExpression","endLine":819,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [currentIndex, latchRecordingTarget]","fix":{"range":[28945,28959],"text":"[currentIndex, latchRecordingTarget]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'clauseRegions' and 'markClauseHeard'. Either include them or remove the dependency array.","line":968,"column":5,"nodeType":"ArrayExpression","endLine":968,"endColumn":41,"suggestions":[{"desc":"Update the dependencies array to be: [clauseRegions, currentIndex, markClauseHeard]","fix":{"range":[34405,34441],"text":"[clauseRegions, currentIndex, markClauseHeard]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useLayoutEffect has a missing dependency: 'setPlaying'. Either include it or remove the dependency array.","line":984,"column":6,"nodeType":"ArrayExpression","endLine":984,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [mediafileId, setPlaying]","fix":{"range":[34830,34843],"text":"[mediafileId, setPlaying]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearOptimistic', 'clearSegmentUndo', 'latchRecordingTarget', and 'resetForScope'. Either include them or remove the dependency array.","line":1042,"column":6,"nodeType":"ArrayExpression","endLine":1042,"endColumn":32,"suggestions":[{"desc":"Update the dependencies array to be: [mediafileId, currentstep, resetForScope, latchRecordingTarget, clearOptimistic, clearSegmentUndo]","fix":{"range":[37620,37646],"text":"[mediafileId, currentstep, resetForScope, latchRecordingTarget, clearOptimistic, clearSegmentUndo]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'latchRecordingTarget', 'memory', and 'removeOptimistic'. Either include them or remove the dependency array.","line":1823,"column":6,"nodeType":"ArrayExpression","endLine":1830,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [recordingRow?.mediafile?.id, recordingRow?.mediafile?.attributes?.audioUrl, removeOptimistic, latchRecordingTarget, applyColors, memory, forceRefresh, stepComplete, currentstep, setStepComplete]","fix":{"range":[62847,62961],"text":"[recordingRow?.mediafile?.id, recordingRow?.mediafile?.attributes?.audioUrl, removeOptimistic, latchRecordingTarget, applyColors, memory, forceRefresh, stepComplete, currentstep, setStepComplete]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import {\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Alert, Box, Typography } from '@mui/material';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport { useGlobal } from '../../context/useGlobal';\nimport usePassageDetailContext from '../../context/usePassageDetailContext';\nimport { useRenderProfiler, useWhyRender } from '../../utils/perf';\nimport PassageDetailPlayer from './PassageDetailPlayer';\nimport StepMessage from './boldClause/StepMessage';\nimport { remoteIdGuid, useArtifactType, useStepTool } from '../../crud';\nimport {\n getSegments,\n getSortedRegions,\n NamedRegions,\n} from '../../utils/namedSegments';\nimport { IRegion } from '../../crud/useWavesurferRegions';\nimport { WSAudioPlayerControls } from '../WSAudioPlayer';\nimport { useOrbitData } from '../../hoc/useOrbitData';\nimport {\n IMediaTabStrings,\n IMediaTitleStrings,\n ISharedStrings,\n MediaFileD,\n} from '../../model';\nimport { passageDefaultFilename } from '../../utils/passageDefaultFilename';\nimport { evictMediaCache } from '../../utils/evictMediaCache';\nimport { related } from '../../crud/related';\nimport { RecordKeyMap } from '@orbit/records';\nimport CarefulSpeechControls, {\n CarefulSpeechPhase,\n} from './carefulSpeech/CarefulSpeechControls';\nimport { useGuidedPhraseSegments } from './carefulSpeech/useGuidedPhraseSegments';\nimport { resolveSegmentSpeaker } from './carefulSpeech/resolveSegmentSpeaker';\nimport {\n CLAUSE_BOUNDARY_THRESHOLD_SEC,\n clauseIndexForRegion,\n hasPhraseRegions,\n preservesRecordedBoundaries,\n regionBoundariesEqual,\n regionsJsonFromList,\n regionsMatch,\n} from './carefulSpeech/carefulSpeechBoundary';\nimport {\n firstIncompleteClauseIndex,\n getCompletedClauseIndices,\n getRecordingForClause,\n} from './carefulSpeech/carefulSpeechCompletion';\nimport {\n matchesGuidedOutputRow,\n phraseBtBoundaryRegionName,\n parseMediaLanguageField,\n} from './carefulSpeech/matchesGuidedOutputRow';\nimport { planLegacyPhraseBtClaim } from './carefulSpeech/claimLegacyPhraseBt';\nimport { UpdateRecord } from '../../model/baseModel';\nimport {\n createCarefulSpeechApplyRegionColor,\n type ICarefulSpeechColorStatus,\n} from '../../utils/carefulSpeechSegmentColors';\nimport { useStepPermissions } from '../../utils/useStepPermission';\nimport { isLinkedNote } from '../../crud/isLinkedNote';\nimport {\n mediaTabSelector,\n mediaTitleSelector,\n sharedSelector,\n} from '../../selector';\nimport { UnsavedContext } from '../../context/UnsavedContext';\nimport {\n applyFewerClauses,\n applyMoreClauses,\n boldDefaultSegParams,\n} from './carefulSpeech/boldCarefulSpeechSegParams';\nimport {\n canCombineWithNext,\n mergeClauseWithNext,\n} from './carefulSpeech/carefulSpeechClauseMerge';\nimport {\n canSplitClause,\n splitClauseAt,\n} from './carefulSpeech/carefulSpeechClauseSplit';\nimport {\n type GuidedPhraseRecordConfig,\n type IGuidedPhraseRecordControlStrings,\n} from '../../components/PassageDetail/guidedPhraseRecord/types';\nimport { createPhraseSegmentUndoStack } from '../../utils/phraseSegmentUndoStack';\nimport Confirm from '../AlertDialog';\nimport { Button } from '../../control/Button';\n\ninterface IProps {\n width: number;\n config: GuidedPhraseRecordConfig;\n controlStrings: IGuidedPhraseRecordControlStrings;\n /** Shown when config.requireBoldWorkflow and the team is not BOLD. */\n workflowGateMessage?: string;\n}\n\n/**\n * A stop reported sooner than this after playback started is the seek that\n * started it, not the audio finishing. Auto-segmenting never produces a clause\n * anywhere near this short.\n */\nconst SPURIOUS_STOP_WINDOW_MS = 250;\n\n/**\n * Slack added to the span a clause is expected to take, so Record is not offered\n * a frame before the audio actually runs out.\n */\nconst CLAUSE_PLAYBACK_MARGIN_MS = 150;\n\nfunction findClauseIndex(clauseRegions: IRegion[], region: IRegion): number {\n return clauseRegions.findIndex(\n (r) =>\n Math.abs(r.start - region.start) < 0.05 &&\n Math.abs(r.end - region.end) < 0.05\n );\n}\n\nexport function PassageDetailGuidedPhraseRecord({\n width,\n config,\n controlStrings,\n workflowGateMessage,\n}: IProps) {\n useRenderProfiler('PassageDetailGuidedPhraseRecord');\n const ts: ISharedStrings = useSelector(sharedSelector, shallowEqual);\n const tm: IMediaTabStrings = useSelector(mediaTabSelector, shallowEqual);\n const tt: IMediaTitleStrings = useSelector(mediaTitleSelector, shallowEqual);\n const [memory] = useGlobal('memory');\n const [user] = useGlobal('user');\n const [plan] = useGlobal('plan');\n const [offline] = useGlobal('offline');\n const mediafiles = useOrbitData('mediafile');\n const [connected] = useGlobal('connected');\n const { getTypeId } = useArtifactType();\n const {\n passage,\n sharedResource,\n playerMediafile,\n mediafileId,\n rowData,\n currentstep,\n section,\n setCurrentSegment,\n setPlaying,\n setRecording,\n forceRefresh,\n currentSegmentIndex,\n /** Change token for the selected segment; see the nav effects below. */\n currentSegmentSeq,\n getCurrentSegment,\n isBoldWorkflow,\n carefulSpeechSegParams,\n setCarefulSpeechSegParams,\n setStepComplete,\n stepComplete,\n } = usePassageDetailContext();\n useWhyRender('PassageDetailGuidedPhraseRecord', {\n passage,\n playerMediafile,\n mediafileId,\n rowData,\n currentstep,\n currentSegmentIndex,\n isBoldWorkflow,\n stepComplete,\n carefulSpeechSegParams,\n mediafiles,\n });\n const { settings } = useStepTool(currentstep);\n const stepSettings = useMemo((): Record => {\n if (!settings) return {};\n if (typeof settings === 'string') {\n try {\n return JSON.parse(settings || '{}') as Record;\n } catch {\n return {};\n }\n }\n return settings as Record;\n }, [settings]);\n const { canDoSectionStep } = useStepPermissions();\n const { startSave, waitForSave } = useContext(UnsavedContext).state;\n\n const stepEnabled = config.requireBoldWorkflow ? isBoldWorkflow : true;\n const [localSegParams, setLocalSegParams] = useState(boldDefaultSegParams);\n const phraseSegParams = config.requireBoldWorkflow\n ? carefulSpeechSegParams\n : localSegParams;\n const setPhraseSegParams = config.requireBoldWorkflow\n ? setCarefulSpeechSegParams\n : setLocalSegParams;\n const toolId = config.mediaRecordToolId;\n\n const playerControlsRef = useRef(null);\n const carefulSpeechStatusRef = useRef(null);\n const applyRegionColor = useMemo(\n () => createCarefulSpeechApplyRegionColor(carefulSpeechStatusRef),\n []\n );\n const bootstrapPollRef = useRef | null>(null);\n const bootstrapCompletedRef = useRef(false);\n const lastResetScopeRef = useRef(undefined);\n const initialPositionDoneRef = useRef(false);\n const suppressClauseAutoPlayRef = useRef(0);\n const playClauseInFlightRef = useRef(false);\n /** Last clause-play start time, used by SPURIOUS_STOP_WINDOW_MS filtering. */\n const clausePlaybackStartedAtRef = useRef(0);\n const entryPauseDoneRef = useRef(false);\n const [highlightPlayButton, setHighlightPlayButton] = useState(false);\n const [allowSourcePlayer, setAllowSourcePlayer] = useState(false);\n const [entryPositioned, setEntryPositioned] = useState(false);\n const [playerPlaying, setPlayerPlaying] = useState(false);\n /**\n * When the clause being played is expected to run out, and whether we are\n * still before it. See recordBlocked.\n */\n const [recordBlockedUntil, setRecordBlockedUntil] = useState(0);\n const [recordBlocked, setRecordBlocked] = useState(false);\n\n const [currentIndex, setCurrentIndex] = useState(0);\n const [phase, setPhase] = useState('bootstrapping');\n const [speaker, setSpeaker] = useState(\n localStorage.getItem(config.speakerLocalKey) ?? ''\n );\n const [showRecorder, setShowRecorder] = useState(false);\n const [resetMedia, setResetMedia] = useState(false);\n const [statusText, setStatusText] = useState('');\n const [canSave, setCanSave] = useState(false);\n const [savingRecording, setSavingRecording] = useState(false);\n // Mirrors saveRejectedRef for render: shows the failure message + Retry.\n const [saveRejected, setSaveRejected] = useState(false);\n // Sync mirror for callbacks so boundary guards see save-start immediately,\n // even before React commits the render update (TT-7427).\n const savingRecordingRef = useRef(false);\n const [recordingPassStarted, setRecordingPassStarted] = useState(false);\n // Sync mirror for region-out callbacks so pass-branching does not read stale\n // state during render lag (TT-7360).\n const recordingPassStartedRef = useRef(false);\n /** Mirrors context recording for segment-lock checks once capture is active. */\n const recordingActiveRef = useRef(false);\n // Armed after auto-play park to ignore one spurious +1 clause jump\n // (overshoot/region-in) while still allowing real navigation (TT-7360).\n const pendingOvershootSwallowRef = useRef(false);\n // Takes saved this session but not yet shown by rowData (TT-7552, TT-7666).\n // Held by the boundaries each take was cut against, not a raw index, so the\n // clause is re-matched to the live layout every recompute and cannot drift\n // when an earlier clause is split or combined (see clauseIndexForRegion).\n const optimisticTakeRegionsRef = useRef([]);\n const [optimisticVersion, setOptimisticVersion] = useState(0);\n const bumpOptimistic = useCallback(\n () => setOptimisticVersion((v) => v + 1),\n []\n );\n const addOptimistic = useCallback(\n (region: IRegion | undefined) => {\n if (!region) return;\n if (\n optimisticTakeRegionsRef.current.some((r) => regionsMatch(r, region))\n ) {\n return;\n }\n optimisticTakeRegionsRef.current = [\n ...optimisticTakeRegionsRef.current,\n { start: region.start, end: region.end },\n ];\n bumpOptimistic();\n },\n [bumpOptimistic]\n );\n const removeOptimistic = useCallback(\n (region: IRegion | undefined) => {\n if (!region) return;\n const kept = optimisticTakeRegionsRef.current.filter(\n (r) => !regionsMatch(r, region)\n );\n if (kept.length !== optimisticTakeRegionsRef.current.length) {\n optimisticTakeRegionsRef.current = kept;\n bumpOptimistic();\n }\n },\n [bumpOptimistic]\n );\n const clearOptimistic = useCallback(() => {\n if (optimisticTakeRegionsRef.current.length === 0) return;\n optimisticTakeRegionsRef.current = [];\n bumpOptimistic();\n }, [bumpOptimistic]);\n const currentIndexRef = useRef(0);\n // Live current-clause region, for the upload callbacks (fire outside render).\n const currentRegionRef = useRef(undefined);\n /** Latched clause/region for the active take until save or discard (TT-7437). */\n const [recordingTarget, setRecordingTarget] = useState<\n { index: number; region: IRegion } | undefined\n >(undefined);\n // Mirror for the upload callbacks, which fire outside a render.\n const recordingTargetRef = useRef<\n { index: number; region: IRegion } | undefined\n >(undefined);\n const latchRecordingTarget = useCallback(\n (target: { index: number; region: IRegion } | undefined) => {\n recordingTargetRef.current = target;\n setRecordingTarget(target);\n },\n []\n );\n const [heardIndices, setHeardIndices] = useState([]);\n const [currentClausePlayed, setCurrentClausePlayed] = useState(false);\n const [combineUndo, setCombineUndo] = useState(null);\n const [segmentUndoCan, setSegmentUndoCan] = useState(false);\n const [resetConfirmText, setResetConfirmText] = useState(null);\n const [baselineSeg, setBaselineSeg] = useState(null);\n const segmentUndoStackRef = useRef(createPhraseSegmentUndoStack());\n const baselineSegRef = useRef(null);\n\n const mediafile = useMemo(\n () => mediafiles.find((m) => m.id === mediafileId),\n [mediafiles, mediafileId]\n );\n\n const artifactTypeId = useMemo((): string => {\n const id = stepSettings.artifactTypeId as string | undefined;\n if (id) {\n return (\n remoteIdGuid('artifacttype', id, memory?.keyMap as RecordKeyMap) ?? id\n );\n }\n return getTypeId(config.defaultArtifactSlug) ?? '';\n }, [stepSettings, memory?.keyMap, getTypeId, config.defaultArtifactSlug]);\n\n const stepLanguageBcp47 = useMemo(() => {\n if (config.requireBoldWorkflow) return undefined;\n const { bcp47 } = parseMediaLanguageField(stepSettings.language);\n return bcp47 !== 'und' ? bcp47 : undefined;\n }, [config.requireBoldWorkflow, stepSettings.language]);\n\n const stepLanguageField = useMemo(() => {\n if (config.requireBoldWorkflow) return undefined;\n const raw = stepSettings.language;\n if (raw == null || raw === '') return undefined;\n const { bcp47 } = parseMediaLanguageField(raw);\n return bcp47 !== 'und' ? String(raw) : undefined;\n }, [config.requireBoldWorkflow, stepSettings.language]);\n\n const currentVersion = mediafile?.attributes?.versionNumber ?? 0;\n\n const hasAnyOutputRecordings = useMemo(\n () =>\n rowData.some((r) =>\n matchesGuidedOutputRow(r, {\n artifactTypeId,\n vernacularMediaId: mediafileId,\n languageBcp47: stepLanguageBcp47,\n })\n ),\n [rowData, artifactTypeId, mediafileId, stepLanguageBcp47]\n );\n\n const claimRanRef = useRef(false);\n useEffect(() => {\n if (\n config.requireBoldWorkflow ||\n !stepLanguageBcp47 ||\n !stepLanguageField ||\n !mediafile ||\n !artifactTypeId ||\n claimRanRef.current\n ) {\n return;\n }\n claimRanRef.current = true;\n const { languageName } = parseMediaLanguageField(stepLanguageField);\n const plan = planLegacyPhraseBtClaim({\n languageName,\n languageBcp47: stepLanguageBcp47,\n artifactTypeId,\n vernacularMedia: [mediafile],\n outputMedia: rowData\n .filter((r) => related(r.mediafile, 'artifactType') === artifactTypeId)\n .map((r) => r.mediafile),\n });\n if (plan.languageUpdates.size === 0 && plan.segmentUpdates.size === 0) {\n return;\n }\n void memory\n .update((t) => {\n const ops = [];\n for (const [id, languagebcp47] of plan.languageUpdates) {\n const m = rowData.find((r) => r.mediafile.id === id)?.mediafile;\n if (!m) continue;\n ops.push(\n ...UpdateRecord(\n t,\n {\n type: 'mediafile',\n id,\n attributes: { ...m.attributes, languagebcp47 },\n } as MediaFileD,\n user\n )\n );\n }\n for (const [id, segments] of plan.segmentUpdates) {\n if (id !== mediafile.id) continue;\n ops.push(\n ...UpdateRecord(\n t,\n {\n type: 'mediafile',\n id,\n attributes: { ...mediafile.attributes, segments },\n } as MediaFileD,\n user\n )\n );\n }\n return ops;\n })\n .then(() => forceRefresh());\n }, [\n config.requireBoldWorkflow,\n stepLanguageBcp47,\n stepLanguageField,\n mediafile,\n artifactTypeId,\n rowData,\n memory,\n user,\n forceRefresh,\n ]);\n\n const verseSegString = useMemo(() => {\n if (!config.constrainAutoSegmentWithVerses || !mediafile) return undefined;\n const verseJson = getSegments(\n NamedRegions.Verse,\n mediafile.attributes?.segments ?? '[]'\n );\n return hasPhraseRegions(verseJson) ? verseJson : undefined;\n }, [config.constrainAutoSegmentWithVerses, mediafile]);\n\n const {\n phraseSegString: clauseSegString,\n setPhraseSegString: setClauseSegString,\n bootstrapped,\n ensureSegments,\n resetForScope,\n resegmentWithParams,\n resetToDefaultSegments,\n persistPhraseSegments: persistClauseSegments,\n } = useGuidedPhraseSegments(mediafile, playerControlsRef, {\n namedRegion:\n stepLanguageBcp47 && config.persistSegments && !config.requireBoldWorkflow\n ? phraseBtBoundaryRegionName(stepLanguageBcp47)\n : config.namedRegion,\n fallbackNamedRegion:\n stepLanguageBcp47 && config.persistSegments && !config.requireBoldWorkflow\n ? NamedRegions.BackTranslation\n : undefined,\n singleSegmentMode: config.singleSegmentMode,\n persistSegments: config.persistSegments,\n constrainAutoSegmentWithVerses: config.constrainAutoSegmentWithVerses,\n shouldReseedFromVerses:\n config.constrainAutoSegmentWithVerses && !hasAnyOutputRecordings,\n });\n\n // TT-7437: a live mirror of clauseSegString. The waveform holds a single,\n // stale onSegment closure (see ADR 0006 / handleRegionPlayEndRef), and one\n // boundary add fires it more than once before React commits. Reading the\n // committed segmentation from that stale closure made pushSegmentUndo\n // photograph an out-of-date state, so a single Undo reverted every edit at\n // once. The undo push and the \"did the boundaries change\" guard read this ref\n // instead of the closure; setClauseSeg keeps it current synchronously so a\n // second fire within one gesture (and the next add) see the real value.\n const clauseSegStringRef = useRef(clauseSegString);\n clauseSegStringRef.current = clauseSegString;\n const setClauseSeg = useCallback(\n (json: string) => {\n clauseSegStringRef.current = json;\n setClauseSegString(json);\n },\n [setClauseSegString]\n );\n\n const clauseRegions = useMemo(\n () => getSortedRegions(clauseSegString),\n [clauseSegString]\n );\n\n const heardSet = useMemo(() => new Set(heardIndices), [heardIndices]);\n const allClausesHeard = useMemo(\n () => clauseRegions.length > 0 && heardSet.size >= clauseRegions.length,\n [heardSet.size, clauseRegions]\n );\n\n const suggestedSegmentsForPlayer = useMemo(() => {\n if (!hasPhraseRegions(clauseSegString)) return undefined;\n return clauseSegString;\n }, [clauseSegString]);\n\n const completedIndices = useMemo(\n () =>\n getCompletedClauseIndices(\n clauseRegions,\n rowData,\n artifactTypeId,\n currentVersion,\n mediafileId,\n config.singleSegmentMode,\n stepLanguageBcp47\n ),\n [\n clauseRegions,\n rowData,\n artifactTypeId,\n currentVersion,\n mediafileId,\n config.singleSegmentMode,\n stepLanguageBcp47,\n ]\n );\n\n // Current clause indices of the optimistically-saved takes, re-matched to the\n // live layout by boundaries so they follow when an earlier clause is split or\n // combined, exactly as completedIndices does (TT-7666).\n const optimisticCompletedIndices = useMemo(() => {\n const indices = new Set();\n for (const region of optimisticTakeRegionsRef.current) {\n const index = clauseIndexForRegion(region, clauseRegions);\n if (index >= 0) indices.add(index);\n }\n return indices;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [clauseRegions, optimisticVersion]);\n\n // A take that finished recording but has not saved yet — its upload failed\n // and it is held for Retry — is still playable and stays latched to the\n // clause it was recorded on. Treat that clause as recorded so its boundaries\n // lock like a saved take's, otherwise a Retry would file it against the altered\n // boundaries (TT-7437). A successful save clears the latch (and the optimistic\n // set then covers the clause), so this only fires for an unsaved take. Matched\n // by boundaries, like the optimistic set, so it tracks the live layout.\n const pendingTakeIndex = useMemo(() => {\n if (phase !== 'recorded' || !recordingTarget) return undefined;\n const index = clauseIndexForRegion(recordingTarget.region, clauseRegions);\n return index >= 0 ? index : undefined;\n }, [phase, recordingTarget, clauseRegions]);\n\n // A segment is treated as recorded (boundary locked, TT-7666) when it has a\n // saved take, a newly saved take that rowData has not shown yet, or a\n // recorded-but-unsaved take latched to it (see pendingTakeIndex above).\n // Keyed on the recorded sets alone: a stored take must freeze its clause even\n // at entry, before runInitialPosition flips recordingPassStarted — that flag\n // lags completedIndices (derived synchronously from rowData), so gating on it\n // left an already-recorded clause editable during the initial-load window.\n const isSegmentRecorded = useCallback(\n (index: number) =>\n completedIndices.has(index) ||\n optimisticCompletedIndices.has(index) ||\n index === pendingTakeIndex,\n [completedIndices, optimisticCompletedIndices, pendingTakeIndex]\n );\n\n /** completedIndices plus the optimistic just-saved set and any latched\n * unsaved take — the single recorded view every boundary-editing guard uses,\n * so they agree in the window before rowData catches up (TT-7666, TT-7437). */\n const recordedClauseIndicesForTools = useMemo(() => {\n const recorded = new Set([\n ...completedIndices,\n ...optimisticCompletedIndices,\n ]);\n if (pendingTakeIndex !== undefined) recorded.add(pendingTakeIndex);\n return recorded;\n }, [completedIndices, optimisticCompletedIndices, pendingTakeIndex]);\n\n const allClausesComplete = useMemo(\n () =>\n clauseRegions.length > 0 && completedIndices.size >= clauseRegions.length,\n [completedIndices, clauseRegions]\n );\n\n // Mirror clause recording coverage into step completion (no auto-advance).\n useEffect(() => {\n if (!bootstrapped || clauseRegions.length === 0) return;\n\n const syncStepComplete = async () => {\n const isComplete = stepComplete(currentstep);\n if (allClausesComplete) {\n if (!isComplete) {\n try {\n await waitForSave(undefined, 200);\n } catch {\n return;\n }\n await setStepComplete(currentstep, true);\n }\n } else if (isComplete) {\n await setStepComplete(currentstep, false);\n }\n };\n\n void syncStepComplete();\n // stepComplete reads psgCompleted internally; waitForSave identity is unstable.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [allClausesComplete, bootstrapped, clauseRegions.length, currentstep]);\n\n const currentRegion = clauseRegions[currentIndex];\n\n const currentClauseSplitPoint = useMemo(() => {\n if (!recordingPassStarted || !currentRegion) return undefined;\n const ctrl = playerControlsRef.current;\n if (!ctrl?.isReady?.() || !ctrl.findClauseSplitPoint) return undefined;\n return ctrl.findClauseSplitPoint(currentRegion, phraseSegParams);\n }, [recordingPassStarted, currentRegion, phraseSegParams]);\n\n const recordingRow = useMemo(\n () =>\n currentRegion\n ? getRecordingForClause(\n rowData,\n artifactTypeId,\n currentVersion,\n currentRegion,\n mediafileId,\n config.singleSegmentMode,\n currentIndex,\n stepLanguageBcp47\n )\n : undefined,\n [\n currentRegion,\n rowData,\n artifactTypeId,\n currentVersion,\n mediafileId,\n config.singleSegmentMode,\n currentIndex,\n stepLanguageBcp47,\n ]\n );\n\n const editStep = useMemo(\n () =>\n canDoSectionStep(currentstep, section) &&\n !isLinkedNote(passage, sharedResource),\n [canDoSectionStep, currentstep, section, passage, sharedResource]\n );\n\n /** The clause a pending take is filed under: latched at Record if there is\n * one, otherwise wherever the user is now. */\n const takeIndex = recordingTarget?.index ?? currentIndex;\n const takeRegion = recordingTarget?.region ?? currentRegion;\n\n const defaultFilename = useMemo(() => {\n const postfix = config.buildFilenamePostfix(\n takeIndex,\n currentVersion,\n stepLanguageBcp47\n );\n return passageDefaultFilename(\n passage,\n plan,\n memory,\n artifactTypeId,\n offline,\n postfix\n );\n }, [\n passage,\n plan,\n memory,\n artifactTypeId,\n offline,\n takeIndex,\n currentVersion,\n stepLanguageBcp47,\n config,\n ]);\n\n carefulSpeechStatusRef.current = {\n currentIndex,\n isCompleted: (i) =>\n recordingPassStarted\n ? completedIndices.has(i) || optimisticCompletedIndices.has(i)\n : heardSet.has(i),\n };\n currentIndexRef.current = currentIndex;\n currentRegionRef.current = currentRegion;\n\n const applyColors = useCallback(() => {\n playerControlsRef.current?.applyRegionColors?.();\n }, []);\n\n // Drop an optimistic take once rowData confirms the clause it now maps to.\n useEffect(() => {\n const kept = optimisticTakeRegionsRef.current.filter((region) => {\n const index = clauseIndexForRegion(region, clauseRegions);\n return !(index >= 0 && completedIndices.has(index));\n });\n if (kept.length !== optimisticTakeRegionsRef.current.length) {\n optimisticTakeRegionsRef.current = kept;\n bumpOptimistic();\n applyColors();\n }\n }, [completedIndices, clauseRegions, applyColors, bumpOptimistic]);\n\n const bumpSuppressClauseAutoPlay = useCallback((count = 1) => {\n suppressClauseAutoPlayRef.current += count;\n }, []);\n\n const consumeSuppressClauseAutoPlay = useCallback(() => {\n if (suppressClauseAutoPlayRef.current > 0) {\n suppressClauseAutoPlayRef.current -= 1;\n return true;\n }\n return false;\n }, []);\n\n useEffect(() => {\n setAllowSourcePlayer(false);\n setPlaying(false);\n const frame = requestAnimationFrame(() => {\n setAllowSourcePlayer(true);\n });\n return () => cancelAnimationFrame(frame);\n // setPlaying is not stable; only reset when mediafile changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [mediafileId]);\n\n useEffect(() => {\n applyColors();\n }, [\n currentIndex,\n completedIndices,\n heardSet,\n recordingPassStarted,\n clauseSegString,\n applyColors,\n ]);\n\n const handleSpeakerChange = useCallback(\n (value: string) => {\n setSpeaker(value);\n localStorage.setItem(config.speakerLocalKey, value);\n },\n [config.speakerLocalKey]\n );\n\n // TT-7440: existing take keeps its performedBy; new takes use last localStorage speaker\n useEffect(() => {\n setSpeaker(\n resolveSegmentSpeaker(\n recordingRow?.mediafile?.attributes?.performedBy,\n config.speakerLocalKey\n )\n );\n }, [recordingRow, currentIndex, config.speakerLocalKey]);\n\n useEffect(() => {\n if (!currentRegion) return;\n const seg = getCurrentSegment();\n if (\n seg &&\n Math.abs(seg.start - currentRegion.start) < 0.05 &&\n Math.abs(seg.end - currentRegion.end) < 0.05\n ) {\n return;\n }\n setCurrentSegment(currentRegion, currentIndex);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentRegion, currentIndex]);\n\n // TT-7583: this step auto-saves on every rising edge of canSave. A failed\n // upload leaves the take dirty, so canSave goes false→true again and we used\n // to retry the same doomed take forever (finalizeTerminalFailure + error\n // snackbar on a loop). MediaRecord tells us the attempt was rejected; hold\n // off until the user records again rather than latching canSave off, which\n // would break the manual Save button on every other recording screen.\n const saveRejectedRef = useRef(false);\n\n const previousConnectedRef = useRef(connected);\n useEffect(() => {\n if (canSave && !saveRejectedRef.current) {\n savingRecordingRef.current = true;\n setSavingRecording(true);\n startSave(toolId);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [canSave]);\n\n // The take is still dirty after a rejection, so asking for the save again is\n // all it takes to re-upload it (TT-7583).\n const handleRetrySave = useCallback(() => {\n saveRejectedRef.current = false;\n setSaveRejected(false);\n savingRecordingRef.current = true;\n setSavingRecording(true);\n startSave(toolId);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [toolId]);\n\n // The failure message belongs to the clause whose take failed. Navigating away\n // clears MediaRecord's blob, so a Retry from another clause would only hit the\n // no-audio branch — drop the message with the take it referred to (TT-7583).\n // Keyed on the index rather than the navigation handlers because every clause\n // move funnels through it.\n useEffect(() => {\n // The latch keeps a take tied to its original clause (TT-7437).\n // If upload failed and the user navigates away, that take is abandoned,\n // so clear the latch here.\n if (saveRejectedRef.current) latchRecordingTarget(undefined);\n saveRejectedRef.current = false;\n setSaveRejected(false);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentIndex]);\n\n useEffect(() => {\n const reconnected = !previousConnectedRef.current && connected;\n previousConnectedRef.current = connected;\n if (reconnected && saveRejectedRef.current && !savingRecordingRef.current) {\n handleRetrySave();\n }\n }, [connected, handleRetrySave]);\n\n const snapToClauseStart = useCallback(\n async (index: number) => {\n const ctrl = playerControlsRef.current;\n const region = clauseRegions[index];\n if (!ctrl?.isReady() || !region) return;\n const seek =\n region.start > 0 ? region.start + CLAUSE_BOUNDARY_THRESHOLD_SEC : 0;\n await ctrl.gotoTime(seek, region);\n applyColors();\n },\n [clauseRegions, applyColors]\n );\n\n const playCurrentClause = useCallback(\n async (index: number = currentIndex, regionOverride?: IRegion) => {\n const ctrl = playerControlsRef.current;\n const region = regionOverride ?? clauseRegions[index];\n if (!ctrl?.isReady() || !region || playClauseInFlightRef.current) return;\n clausePlaybackStartedAtRef.current = Date.now();\n playClauseInFlightRef.current = true;\n try {\n setPhase('playing');\n const seek =\n region.start > 0 ? region.start + CLAUSE_BOUNDARY_THRESHOLD_SEC : 0;\n // Compute expected playback span so Record stays disabled for the full\n // clause duration. Use rate for future speed-enabled flows.\n const rate = ctrl.getPlaybackRate?.() || 1;\n setRecordBlockedUntil(\n Date.now() +\n (Math.max(0, region.end - seek) * 1000) / rate +\n CLAUSE_PLAYBACK_MARGIN_MS\n );\n await ctrl.gotoTime(seek, region);\n ctrl.setPlay(true);\n } finally {\n playClauseInFlightRef.current = false;\n }\n },\n [clauseRegions, currentIndex]\n );\n\n const pushSegmentUndo = useCallback(() => {\n if (!config.multiLevelSegmentUndo) return;\n // Read live segmentation from the ref, not from a stale render closure\n // (TT-7437). See clauseSegStringRef above.\n const snapshot = clauseSegStringRef.current;\n if (!hasPhraseRegions(snapshot)) return;\n // handleSegment already filters duplicate boundary events by comparing\n // incoming boundaries to the live ref (regionBoundariesEqual), so this\n // records at most one entry per real boundary change (TT-7437).\n segmentUndoStackRef.current.push(snapshot);\n setSegmentUndoCan(segmentUndoStackRef.current.canUndo());\n }, [config.multiLevelSegmentUndo]);\n\n const clearSegmentUndo = useCallback(() => {\n segmentUndoStackRef.current.clear();\n setSegmentUndoCan(false);\n }, []);\n\n const resetListenProgress = useCallback(() => {\n setHeardIndices([]);\n setCurrentIndex(0);\n setCombineUndo(null);\n }, []);\n\n const applyResegmentResult = useCallback(\n async (ok: string | false) => {\n if (!ok) return;\n resetListenProgress();\n setPhase('readyToRecord');\n const regions = getSortedRegions(ok);\n const first = regions[0];\n if (first) {\n bumpSuppressClauseAutoPlay(4);\n setCurrentIndex(0);\n setCurrentSegment(first, 0);\n await snapToClauseStart(0);\n }\n setHighlightPlayButton(true);\n applyColors();\n },\n [\n resetListenProgress,\n applyColors,\n snapToClauseStart,\n setCurrentSegment,\n bumpSuppressClauseAutoPlay,\n ]\n );\n\n const handlePlayStatusNotify = useCallback(\n (playingNow: boolean) => {\n if (playingNow) {\n setHighlightPlayButton(false);\n // Reset stop-filter timing at every playback start.\n clausePlaybackStartedAtRef.current = Date.now();\n // Also gate Record for user-triggered replays from current playhead.\n // Set here (not beforePlay) so playback start is not interrupted.\n const region = clauseRegions[currentIndex];\n const ctrl = playerControlsRef.current;\n if (region && ctrl) {\n const from = ctrl.getProgress?.() ?? region.start;\n const rate = ctrl.getPlaybackRate?.() || 1;\n const remainingMs = (Math.max(0, region.end - from) * 1000) / rate;\n if (remainingMs > 0) {\n setRecordBlockedUntil(\n Date.now() + remainingMs + CLAUSE_PLAYBACK_MARGIN_MS\n );\n }\n }\n }\n if (currentIndex === clauseRegions.length - 1) {\n markClauseHeard(currentIndex);\n }\n // Only a stop tells us the clause has been heard; the start case is\n // handled above.\n if (playingNow) return;\n // The listen pass has nothing to record, so nothing to enable.\n if (!recordingPassStartedRef.current) return;\n // Capturing or saving a take stops the source audio, and that stop is not\n // the clause being heard. Defensive:\n if (recordingActiveRef.current || savingRecordingRef.current) return;\n // Ignore synthetic stop from start seek if it lands inside the spurious\n // stop window.\n if (\n Date.now() - clausePlaybackStartedAtRef.current <\n SPURIOUS_STOP_WINDOW_MS\n ) {\n return;\n }\n // Real user pause: release Record block and mark clause as heard.\n // Very-early pauses are treated like start-seek noise by design.\n setRecordBlockedUntil(0);\n setCurrentClausePlayed(true);\n setPhase((p) =>\n p === 'recording' || p === 'recorded' ? p : 'recordReady'\n );\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [clauseRegions.length, currentIndex]\n );\n\n const setPlayerPlayingBoth = useCallback(\n (playingNow: boolean) => {\n setPlayerPlaying(playingNow);\n setPlaying(playingNow);\n },\n [setPlaying]\n );\n\n useLayoutEffect(() => {\n setPlayerPlaying(false);\n setPlaying(false);\n // setPlaying is not stable; only reset when mediafile changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [mediafileId]);\n\n useEffect(() => {\n // StrictMode double-invokes effects on mount (setup → cleanup → setup) and\n // refs persist across that re-run. Without this guard the second invocation\n // re-resets recordingPassStarted to false and clears initialPositionDoneRef\n // mid-entry, clobbering an already-started recording pass and dropping the\n // user back into the listen pass (TT-7360). Only reset once per actual\n // mediafile change.\n //\n // The step is part of that identity, not just the mediafile: a team can\n // configure a Phrase BT step per language, and every one of them renders\n // this same component against the same vernacular. Where the route does not\n // remount it between steps, keying the reset on the mediafile alone carried\n // the previous language's recording pass - its clause index, its baseline\n // boundaries, its optimistic greens, and the take showing in the recorder -\n // into the next language's step (TT-7643).\n if (!currentstep) return;\n const stepScope = `${mediafileId ?? ''}|${currentstep}`;\n if (lastResetScopeRef.current === stepScope) return;\n lastResetScopeRef.current = stepScope;\n resetForScope(mediafileId);\n // The legacy claim is per step language, so a reused instance has to be\n // allowed to run it again for the step just moved to.\n claimRanRef.current = false;\n bootstrapCompletedRef.current = false;\n setPhase('bootstrapping');\n setCurrentIndex(0);\n setRecordingPassStarted(false);\n recordingPassStartedRef.current = false;\n recordingActiveRef.current = false;\n savingRecordingRef.current = false;\n setSavingRecording(false);\n saveRejectedRef.current = false;\n setSaveRejected(false);\n pendingOvershootSwallowRef.current = false;\n // The latch is mediafile-specific. Clear it when source media changes,\n // so the next take cannot reuse a clause from the old waveform (TT-7437).\n latchRecordingTarget(undefined);\n clearOptimistic();\n setHeardIndices([]);\n setCurrentClausePlayed(false);\n setCombineUndo(null);\n clearSegmentUndo();\n baselineSegRef.current = null;\n setBaselineSeg(null);\n setShowRecorder(false);\n entryPauseDoneRef.current = false;\n initialPositionDoneRef.current = false;\n setEntryPositioned(false);\n suppressClauseAutoPlayRef.current = 0;\n setHighlightPlayButton(false);\n // Gate only on the stable mediafileId / currentstep strings.\n // resetForScope's identity changes whenever the mediafile record is\n // updated (e.g. persisting combined clause segments), which would otherwise\n // re-fire this reset and drop the user from the recording pass back into\n // the listen pass (TT-7360).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [mediafileId, currentstep]);\n\n useEffect(() => {\n if (!mediafileId || !stepEnabled) return;\n\n const stopPoll = () => {\n if (bootstrapPollRef.current) {\n clearInterval(bootstrapPollRef.current);\n bootstrapPollRef.current = null;\n }\n };\n\n const tryBootstrap = async () => {\n if (bootstrapCompletedRef.current) {\n stopPoll();\n return;\n }\n const ok = await ensureSegments();\n if (!ok) return;\n bootstrapCompletedRef.current = true;\n stopPoll();\n setPhase('readyToRecord');\n applyColors();\n };\n\n void tryBootstrap();\n bootstrapPollRef.current = setInterval(() => {\n void tryBootstrap();\n }, 250);\n\n return stopPoll;\n }, [mediafileId, ensureSegments, applyColors, stepEnabled]);\n\n useEffect(() => {\n if (!bootstrapped || !hasPhraseRegions(clauseSegString)) return;\n if (baselineSegRef.current === null) {\n baselineSegRef.current = clauseSegString;\n setBaselineSeg(clauseSegString);\n clearSegmentUndo();\n }\n }, [bootstrapped, clauseSegString, clearSegmentUndo]);\n\n useEffect(() => {\n if (!bootstrapped || !stepEnabled || !allowSourcePlayer) {\n return;\n }\n\n const runInitialPosition = (): boolean => {\n if (initialPositionDoneRef.current) return true;\n if (clauseRegions.length === 0) return false;\n const ctrl = playerControlsRef.current;\n if (!ctrl?.isReady()) return false;\n\n initialPositionDoneRef.current = true;\n const completed = getCompletedClauseIndices(\n clauseRegions,\n rowData,\n artifactTypeId,\n currentVersion,\n mediafileId,\n config.singleSegmentMode,\n stepLanguageBcp47\n );\n const firstIdx = firstIncompleteClauseIndex(clauseRegions, completed);\n if (firstIdx >= clauseRegions.length) {\n // All clauses recorded: enter review mode on first clause.\n setRecordingPassStarted(true);\n recordingPassStartedRef.current = true;\n setShowRecorder(true);\n setCurrentIndex(0);\n setCurrentSegment(clauseRegions[0], 0);\n setCurrentClausePlayed(true);\n setPhase('recorded');\n void snapToClauseStart(0);\n applyColors();\n setEntryPositioned(true);\n return true;\n }\n\n const hasRecordings = completed.size > 0;\n if (hasRecordings) {\n setRecordingPassStarted(true);\n recordingPassStartedRef.current = true;\n setShowRecorder(true);\n }\n\n setCurrentIndex(firstIdx);\n setCurrentSegment(clauseRegions[firstIdx], firstIdx);\n setPhase('readyToRecord');\n\n if (hasRecordings) {\n // Recording pass: auto-play the first unrecorded clause once.\n // region-out will stop and snap the playhead back to the clause start.\n setCurrentClausePlayed(false);\n setHighlightPlayButton(false);\n void playCurrentClause(firstIdx);\n } else {\n // Listen pass: position and wait for the user to tap play.\n bumpSuppressClauseAutoPlay(4);\n setHighlightPlayButton(true);\n void snapToClauseStart(firstIdx);\n }\n applyColors();\n setEntryPositioned(true);\n return true;\n };\n\n if (runInitialPosition()) return;\n\n const pollRef = setInterval(() => {\n if (runInitialPosition()) {\n clearInterval(pollRef);\n }\n }, 250);\n\n return () => clearInterval(pollRef);\n }, [\n bootstrapped,\n stepEnabled,\n allowSourcePlayer,\n clauseRegions,\n rowData,\n artifactTypeId,\n currentVersion,\n mediafileId,\n config.singleSegmentMode,\n snapToClauseStart,\n setCurrentSegment,\n applyColors,\n bumpSuppressClauseAutoPlay,\n playCurrentClause,\n stepLanguageBcp47,\n ]);\n\n const handleSegment = useCallback(\n async (seg: string, init: boolean) => {\n if (init) {\n setClauseSeg(seg);\n return;\n }\n // Read recording guards from refs: handleSegment is the once-registered\n // onSegment callback, so its render closure is stale (TT-7437, ADR 0012).\n if (recordingActiveRef.current || savingRecordingRef.current) return;\n const regions = getSortedRegions(seg);\n if (regions.length === 0) return;\n // Defense-in-depth only: if an update still changes recorded boundaries,\n // reload the previous regions. Main blocking now happens earlier in\n // useWavesurferRegions (drag, split/merge, and +/- controls; TT-7666).\n // Use the same recorded view every other guard reads (completed +\n // optimistic + pending), so a just-saved clause is protected here too\n // before rowData catches up.\n //\n // POSSIBLY STALE (TT-7437): handleSegment is the once-registered onSegment\n // callback, so its closure freezes at audio-load time. `clauseRegions`\n // (from clauseSegString) and `recordedClauseIndicesForTools` (completed +\n // optimistic + pending) are read from that closure, so they can lag the\n // real recorded picture until the next audio load. `regions` (the live\n // event arg) is current, as is the recordingPassStartedRef gate.\n // Why this is not expected to misbehave: the gate is live, so the check\n // runs/skips correctly, and the real block is upstream in\n // useWaveSurferRegions — this guard only fires when that already missed.\n // Not hand-mirrored to refs here because a live recordedClauseIndicesForTools\n // needs rowData/artifactType/version/mediafile/language refs too, and a\n // partial fix would compare live regions against a stale recorded set.\n // ADR 0012 Layer 2 makes the callback itself live, refreshing both reads.\n if (\n recordingPassStartedRef.current &&\n !preservesRecordedBoundaries(\n clauseRegions,\n regions,\n recordedClauseIndicesForTools\n )\n ) {\n playerControlsRef.current?.loadRegionsJson?.(\n clauseSegStringRef.current\n );\n return;\n }\n const json = regionsJsonFromList(regions, phraseSegParams);\n // Compare against the live segmentation (TT-7437): a stale closure would\n // otherwise let a second fire of the same gesture through as a fresh edit.\n if (regionBoundariesEqual(json, clauseSegStringRef.current)) return;\n pushSegmentUndo();\n setClauseSeg(json);\n await persistClauseSegments(json);\n applyColors();\n },\n [\n setClauseSeg,\n persistClauseSegments,\n phraseSegParams,\n applyColors,\n clauseRegions,\n recordedClauseIndicesForTools,\n clauseSegString,\n pushSegmentUndo,\n ]\n );\n\n const markClauseHeard = useCallback((index: number) => {\n setHeardIndices((prev) =>\n prev.includes(index) ? prev : [...prev, index].sort((a, b) => a - b)\n );\n }, []);\n\n const handleRegionPlayEnd = useCallback(\n (region: IRegion) => {\n const idx = findClauseIndex(clauseRegions, region);\n if (idx < 0) return;\n\n if (!recordingPassStartedRef.current) {\n playerControlsRef.current?.setPlay(false);\n markClauseHeard(idx);\n if (idx < clauseRegions.length - 1) {\n const next = idx + 1;\n bumpSuppressClauseAutoPlay(4);\n setCurrentIndex(next);\n const nextRegion = clauseRegions[next];\n setCurrentSegment(nextRegion, next);\n void snapToClauseStart(next);\n setHighlightPlayButton(true);\n } else {\n setCurrentIndex(idx);\n }\n setPhase('readyToRecord');\n applyColors();\n return;\n }\n\n setCurrentIndex(idx);\n setCurrentClausePlayed(true);\n // After auto-play park, ignore one spurious +1 region change caused by\n // overshoot or recorder mount (TT-7360).\n pendingOvershootSwallowRef.current = true;\n if (phase === 'recording') return;\n setPhase('recordReady');\n applyColors();\n },\n [\n clauseRegions,\n phase,\n applyColors,\n markClauseHeard,\n bumpSuppressClauseAutoPlay,\n setCurrentSegment,\n snapToClauseStart,\n ]\n );\n\n // region-out listener is registered once; route through ref to avoid stale\n // closure when recording pass changes without audio reload (ADR 0006).\n const handleRegionPlayEndRef = useRef(handleRegionPlayEnd);\n handleRegionPlayEndRef.current = handleRegionPlayEnd;\n const onSegmentPlaybackEnd = useCallback((region: IRegion) => {\n handleRegionPlayEndRef.current(region);\n }, []);\n\n /** User click is intentional navigation, so never treat it as overshoot. */\n const handleSegmentClick = useCallback(() => {\n pendingOvershootSwallowRef.current = false;\n }, []);\n\n useEffect(() => {\n if (!bootstrapped || !entryPositioned || entryPauseDoneRef.current) return;\n if (recordingPassStarted) return; // recording pass auto-plays on entry; don't pause\n entryPauseDoneRef.current = true;\n playerControlsRef.current?.setPlay(false);\n setPlayerPlaying(false);\n }, [bootstrapped, entryPositioned, recordingPassStarted]);\n\n useEffect(() => {\n const seg = getCurrentSegment();\n if (!seg || clauseRegions.length === 0 || !recordingPassStarted) return;\n if (!entryPositioned) return;\n if (recordingActiveRef.current || savingRecording) return;\n const idx = findClauseIndex(clauseRegions, seg);\n if (idx < 0) return;\n\n const indexChanged = idx !== currentIndex;\n\n if (pendingOvershootSwallowRef.current && idx === currentIndex + 1) {\n // Swallow one adjacent +1 change right after auto-play park. It is\n // usually overshoot/region-in noise, not user navigation (TT-7621).\n pendingOvershootSwallowRef.current = false;\n if (playerControlsRef.current?.isPlaying?.()) {\n playerControlsRef.current.setPlay(false);\n }\n setCurrentSegment(clauseRegions[currentIndex], currentIndex);\n void snapToClauseStart(currentIndex);\n return;\n }\n\n if (completedIndices.has(idx)) {\n if (playerControlsRef.current?.isPlaying?.()) {\n playerControlsRef.current.setPlay(false);\n }\n if (indexChanged) {\n // TT-7552: clear prior take from MediaRecord when changing segments.\n setResetMedia(true);\n setCurrentIndex(idx);\n setCurrentSegment(clauseRegions[idx], idx);\n }\n setShowRecorder(true);\n setPhase('recorded');\n setCurrentClausePlayed(true);\n void snapToClauseStart(idx);\n return;\n }\n\n // Only stop playback when the user actually navigates to a different\n // clause. The region-in event that fires when the current clause starts\n // playing also bumps currentSegmentIndex; pausing here unconditionally\n // would kill that playback the instant it begins (TT-7360).\n if (!indexChanged) return;\n\n if (playerControlsRef.current?.isPlaying?.()) {\n playerControlsRef.current.setPlay(false);\n }\n\n // Genuine navigation (user tap) — cancel any armed swallow and play it.\n pendingOvershootSwallowRef.current = false;\n\n // TT-7552: clear prior take so Segment N+1 starts empty (same as Next Clause).\n setResetMedia(true);\n setCurrentIndex(idx);\n setCurrentSegment(clauseRegions[idx], idx);\n setShowRecorder(true);\n setCurrentClausePlayed(false);\n setPhase((p) => (p === 'recording' ? 'recording' : 'readyToRecord'));\n void playCurrentClause(idx);\n // Both deps are change signals for getCurrentSegment(). Keep\n // currentSegmentSeq for reliable move detection across index conventions,\n // and keep currentSegmentIndex for row-change resets that skip seq bumps.\n }, [\n currentSegmentIndex,\n currentSegmentSeq,\n clauseRegions,\n currentIndex,\n completedIndices,\n getCurrentSegment,\n recordingPassStarted,\n entryPositioned,\n setCurrentSegment,\n playCurrentClause,\n snapToClauseStart,\n savingRecording,\n ]);\n\n useEffect(() => {\n const seg = getCurrentSegment();\n if (!seg || clauseRegions.length === 0 || recordingPassStarted) return;\n if (!entryPositioned) return;\n const idx = findClauseIndex(clauseRegions, seg);\n if (idx < 0 || idx === currentIndex) return;\n\n if (playerControlsRef.current?.isPlaying?.()) {\n playerControlsRef.current.setPlay(false);\n }\n setCurrentIndex(idx);\n setCurrentSegment(clauseRegions[idx], idx);\n if (!consumeSuppressClauseAutoPlay()) {\n void playCurrentClause(idx);\n }\n // See the recording-pass effect above for why currentSegmentSeq is a dep.\n }, [\n currentSegmentIndex,\n currentSegmentSeq,\n clauseRegions,\n currentIndex,\n getCurrentSegment,\n recordingPassStarted,\n entryPositioned,\n setCurrentSegment,\n playCurrentClause,\n consumeSuppressClauseAutoPlay,\n ]);\n\n const [changeLength, setChangeLength] = useState(false);\n\n const handleMoreClauses = useCallback(async () => {\n if (recordingPassStarted) return;\n pushSegmentUndo();\n const nextParams = applyMoreClauses(phraseSegParams, changeLength);\n setPhraseSegParams(nextParams);\n setChangeLength(!changeLength);\n const ok = await resegmentWithParams(nextParams);\n await applyResegmentResult(ok);\n }, [\n recordingPassStarted,\n phraseSegParams,\n setPhraseSegParams,\n changeLength,\n resegmentWithParams,\n applyResegmentResult,\n pushSegmentUndo,\n ]);\n\n const handleFewerClauses = useCallback(async () => {\n if (recordingPassStarted) return;\n pushSegmentUndo();\n const nextParams = applyFewerClauses(phraseSegParams, changeLength);\n setPhraseSegParams(nextParams);\n setChangeLength(!changeLength);\n const ok = await resegmentWithParams(nextParams);\n await applyResegmentResult(ok);\n }, [\n recordingPassStarted,\n phraseSegParams,\n setPhraseSegParams,\n changeLength,\n resegmentWithParams,\n applyResegmentResult,\n pushSegmentUndo,\n ]);\n\n const performStepBaselineReset = useCallback(async () => {\n const baseline = baselineSegRef.current;\n if (!baseline) return;\n const toDelete = rowData.filter((r) =>\n matchesGuidedOutputRow(r, {\n artifactTypeId,\n vernacularMediaId: mediafileId,\n languageBcp47: stepLanguageBcp47,\n })\n );\n if (toDelete.length > 0) {\n await memory.update((t) =>\n toDelete.map((r) =>\n t.removeRecord({ type: 'mediafile', id: r.mediafile.id })\n )\n );\n // TT-7689: evict the deleted takes from the basename-keyed desktop media\n // cache so a re-record with the same server name can't play stale audio.\n await Promise.all(\n toDelete.map((r) => evictMediaCache(r.mediafile.attributes?.audioUrl))\n );\n }\n clearSegmentUndo();\n setCombineUndo(null);\n setClauseSeg(baseline);\n await persistClauseSegments(baseline);\n playerControlsRef.current?.loadRegionsJson?.(baseline);\n setRecordingPassStarted(false);\n recordingPassStartedRef.current = false;\n clearOptimistic();\n setShowRecorder(false);\n setHeardIndices([]);\n setCurrentClausePlayed(false);\n setCurrentIndex(0);\n setPhase('readyToRecord');\n const regions = getSortedRegions(baseline);\n if (regions[0]) {\n bumpSuppressClauseAutoPlay(4);\n setCurrentSegment(regions[0], 0);\n await snapToClauseStart(0);\n }\n setHighlightPlayButton(true);\n if (stepComplete(currentstep)) {\n await setStepComplete(currentstep, false);\n }\n forceRefresh();\n applyColors();\n }, [\n rowData,\n artifactTypeId,\n mediafileId,\n stepLanguageBcp47,\n memory,\n clearSegmentUndo,\n setClauseSeg,\n persistClauseSegments,\n bumpSuppressClauseAutoPlay,\n setCurrentSegment,\n snapToClauseStart,\n stepComplete,\n currentstep,\n setStepComplete,\n forceRefresh,\n applyColors,\n clearOptimistic,\n ]);\n\n const handleClearSegments = useCallback(async () => {\n if (config.showSegmentResetInRecordingPass) {\n if (!recordingPassStarted) return;\n const baseline = baselineSegRef.current;\n if (!baseline) return;\n const boundariesChanged = !regionBoundariesEqual(\n baseline,\n clauseSegString\n );\n if (!boundariesChanged && !hasAnyOutputRecordings) return;\n const text = hasAnyOutputRecordings\n ? (controlStrings.resetConfirmRecordings ??\n 'Resetting will delete all recordings and restore segment boundaries. Continue?')\n : (controlStrings.resetConfirmBoundaries ??\n 'Resetting will restore segment boundaries. Continue?');\n setResetConfirmText(text);\n return;\n }\n if (recordingPassStarted) return;\n setPhraseSegParams(boldDefaultSegParams);\n setShowRecorder(false);\n const ok = await resetToDefaultSegments();\n await applyResegmentResult(ok);\n }, [\n config.showSegmentResetInRecordingPass,\n recordingPassStarted,\n clauseSegString,\n hasAnyOutputRecordings,\n controlStrings.resetConfirmRecordings,\n controlStrings.resetConfirmBoundaries,\n setPhraseSegParams,\n resetToDefaultSegments,\n applyResegmentResult,\n ]);\n\n const handleSplitClause = useCallback(async () => {\n if (savingRecordingRef.current) return;\n const region = clauseRegions[currentIndex];\n if (!region) return;\n const splitPoint = playerControlsRef.current?.findClauseSplitPoint?.(\n region,\n phraseSegParams\n );\n if (\n !canSplitClause(\n currentIndex,\n clauseRegions,\n recordedClauseIndicesForTools,\n splitPoint\n )\n ) {\n return;\n }\n const updated = splitClauseAt(clauseRegions, currentIndex, splitPoint!);\n if (!updated) return;\n if (config.multiLevelSegmentUndo) {\n pushSegmentUndo();\n } else {\n setCombineUndo(clauseSegString);\n }\n const json = regionsJsonFromList(updated, phraseSegParams);\n setClauseSeg(json);\n await persistClauseSegments(json);\n playerControlsRef.current?.loadRegionsJson?.(json);\n applyColors();\n const firstSubClause = updated[currentIndex];\n setCurrentSegment(firstSubClause, currentIndex);\n setCurrentClausePlayed(false);\n setPhase('readyToRecord');\n void playCurrentClause(currentIndex, firstSubClause);\n }, [\n currentIndex,\n clauseRegions,\n recordedClauseIndicesForTools,\n clauseSegString,\n phraseSegParams,\n setClauseSeg,\n persistClauseSegments,\n applyColors,\n setCurrentSegment,\n playCurrentClause,\n config.multiLevelSegmentUndo,\n pushSegmentUndo,\n ]);\n\n const handleCombineWithNext = useCallback(async () => {\n if (savingRecordingRef.current) return;\n if (\n !canCombineWithNext(\n currentIndex,\n clauseRegions,\n recordedClauseIndicesForTools\n )\n ) {\n return;\n }\n const updated = mergeClauseWithNext(clauseRegions, currentIndex);\n if (!updated) return;\n if (config.multiLevelSegmentUndo) {\n pushSegmentUndo();\n } else {\n setCombineUndo(clauseSegString);\n }\n const json = regionsJsonFromList(updated, phraseSegParams);\n setClauseSeg(json);\n await persistClauseSegments(json);\n playerControlsRef.current?.loadRegionsJson?.(json);\n applyColors();\n void playCurrentClause(currentIndex, updated[currentIndex]);\n }, [\n currentIndex,\n clauseRegions,\n recordedClauseIndicesForTools,\n clauseSegString,\n phraseSegParams,\n setClauseSeg,\n persistClauseSegments,\n applyColors,\n playCurrentClause,\n config.multiLevelSegmentUndo,\n pushSegmentUndo,\n ]);\n\n const handleUndoCombine = useCallback(async () => {\n if (savingRecordingRef.current) return;\n if (!combineUndo) return;\n setClauseSeg(combineUndo);\n await persistClauseSegments(combineUndo);\n playerControlsRef.current?.loadRegionsJson?.(combineUndo);\n setCombineUndo(null);\n applyColors();\n void playCurrentClause(currentIndex);\n }, [\n combineUndo,\n setClauseSeg,\n persistClauseSegments,\n applyColors,\n playCurrentClause,\n currentIndex,\n ]);\n\n const handleSegmentUndo = useCallback(async () => {\n // Guard before pop() so a blocked undo doesn't consume a stack entry.\n if (savingRecordingRef.current) return;\n const prev = segmentUndoStackRef.current.pop();\n setSegmentUndoCan(segmentUndoStackRef.current.canUndo());\n if (!prev) return;\n setClauseSeg(prev);\n await persistClauseSegments(prev);\n playerControlsRef.current?.loadRegionsJson?.(prev);\n if (!recordingPassStarted) {\n await applyResegmentResult(prev);\n } else {\n applyColors();\n const regions = getSortedRegions(prev);\n const idx = Math.min(currentIndex, Math.max(0, regions.length - 1));\n setCurrentIndex(idx);\n if (regions[idx]) {\n setCurrentSegment(regions[idx], idx);\n void playCurrentClause(idx, regions[idx]);\n }\n }\n }, [\n setClauseSeg,\n persistClauseSegments,\n recordingPassStarted,\n applyResegmentResult,\n applyColors,\n currentIndex,\n setCurrentSegment,\n playCurrentClause,\n ]);\n\n const handleStartRecording = useCallback(() => {\n setRecordingPassStarted(true);\n recordingPassStartedRef.current = true;\n setHeardIndices([]);\n setShowRecorder(true);\n setCombineUndo(null);\n const next = firstIncompleteClauseIndex(clauseRegions, completedIndices);\n if (next >= clauseRegions.length) {\n setCurrentIndex(0);\n setCurrentSegment(clauseRegions[0], 0);\n setCurrentClausePlayed(true);\n setPhase('recorded');\n void snapToClauseStart(0);\n applyColors();\n return;\n }\n setCurrentIndex(next);\n const region = clauseRegions[next];\n setCurrentSegment(region, next);\n setCurrentClausePlayed(false);\n setPhase('readyToRecord');\n setHighlightPlayButton(false);\n void playCurrentClause(next);\n }, [\n clauseRegions,\n completedIndices,\n setCurrentSegment,\n playCurrentClause,\n snapToClauseStart,\n applyColors,\n ]);\n\n const handleNextClause = useCallback(async () => {\n if (savingRecording) return;\n const effectiveCompleted = new Set(completedIndices);\n effectiveCompleted.add(currentIndex);\n const next = firstIncompleteClauseIndex(clauseRegions, effectiveCompleted);\n if (next >= clauseRegions.length) {\n setCurrentClausePlayed(true);\n setPhase('recorded');\n applyColors();\n return;\n }\n setCurrentIndex(next);\n const region = clauseRegions[next];\n setCurrentSegment(region, next);\n setCurrentClausePlayed(false);\n setPhase('readyToRecord');\n setResetMedia(true);\n // Play next once; region-end handler parks on it and arms overshoot swallow\n // so next+1 region-in does not auto-advance (TT-7360).\n await playCurrentClause(next);\n }, [\n clauseRegions,\n completedIndices,\n currentIndex,\n setCurrentSegment,\n playCurrentClause,\n applyColors,\n savingRecording,\n ]);\n\n const afterUploadCb = useCallback(\n async (mediaId: string | undefined) => {\n // Mark optimistic completion immediately after real upload (TT-7552),\n // and always apply it to the latched recording-start clause (TT-7437).\n // No mediaId means upload failed; do not show optimistic success (TT-7583).\n const takeRegion =\n recordingTargetRef.current?.region ?? currentRegionRef.current;\n if (mediaId) {\n addOptimistic(takeRegion);\n // Stored: the take is no longer pending, so release the clause.\n latchRecordingTarget(undefined);\n } else {\n removeOptimistic(takeRegion);\n // Keep the latch on failed upload so Retry files to the same clause\n // even if selection moved (TT-7583).\n }\n // Keep 'recorded' on success or failure so user can clear/retry this take\n // instead of starting a new one accidentally (TT-7583).\n setPhase('recorded');\n savingRecordingRef.current = false;\n setSavingRecording(false);\n forceRefresh();\n setResetMedia(false);\n applyColors();\n },\n [\n forceRefresh,\n applyColors,\n latchRecordingTarget,\n addOptimistic,\n removeOptimistic,\n ]\n );\n\n const handleClearRecording = useCallback(async () => {\n // Clearing the take also clears failed-save state and latch (TT-7583).\n saveRejectedRef.current = false;\n setSaveRejected(false);\n // Failed uploads may have no mediafile record, but Clear still discards the\n // local take (TT-7583).\n const mediaId = recordingRow?.mediafile?.id;\n if (mediaId) {\n const audioUrl = recordingRow?.mediafile?.attributes?.audioUrl;\n await memory.update((t) =>\n t.removeRecord({ type: 'mediafile', id: mediaId })\n );\n // TT-7689: evict the cleared take from the basename-keyed desktop media\n // cache so re-recording under the same server name can't play it back.\n await evictMediaCache(audioUrl);\n forceRefresh();\n if (stepComplete(currentstep)) {\n await setStepComplete(currentstep, false);\n }\n }\n removeOptimistic(\n recordingTargetRef.current?.region ?? currentRegionRef.current\n );\n // The take is gone, so the clause it was held against is released too.\n latchRecordingTarget(undefined);\n setPhase('recordReady');\n setCurrentClausePlayed(true);\n setResetMedia(true);\n applyColors();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n recordingRow,\n forceRefresh,\n applyColors,\n currentstep,\n stepComplete,\n setStepComplete,\n ]);\n\n const allowRecord =\n recordingPassStarted &&\n currentClausePlayed &&\n (phase === 'recordReady' || phase === 'recording') &&\n // Same recorded view the boundary guards use (completed + optimistic +\n // pending), so a just-saved clause can't be re-recorded before rowData\n // catches up (TT-7666).\n !recordedClauseIndicesForTools.has(currentIndex);\n\n /**\n * Disable only the Record button until expected clause playback time expires.\n *\n * We use time-based gating because early region-out events from start seeks\n * can look like real playback end and re-enable Record too soon (ADR 0011).\n *\n * This is intentionally separate from allowRecord so recorder capability and\n * mic lifecycle state are not toggled by this temporary UI gate.\n */\n useEffect(() => {\n const remaining = recordBlockedUntil - Date.now();\n if (remaining <= 0) {\n setRecordBlocked(false);\n return;\n }\n setRecordBlocked(true);\n const timer = setTimeout(() => setRecordBlocked(false), remaining);\n return () => clearTimeout(timer);\n }, [recordBlockedUntil]);\n const highlightSpeaker =\n recordingPassStarted && showRecorder && !speaker.trim();\n\n if (config.requireBoldWorkflow && !isBoldWorkflow) {\n return ;\n }\n\n if (!config.requireBoldWorkflow && !stepLanguageBcp47) {\n return (\n \n );\n }\n\n if (!mediafileId) {\n return ;\n }\n\n // Single source of truth for the segment-selection lock. While it is up,\n // useWavesurferRegions.handleRegionClick drops waveform clicks silently, so\n // it is mirrored onto the container: a test that clicks a segment has no\n // other way to know whether the click could be received (TT-7360 follow-up).\n const segmentSelectionLocked = phase === 'recording' || savingRecording;\n\n return (\n \n {allowSourcePlayer && (\n void handleSegmentUndo()\n : undefined\n }\n controlsRef={playerControlsRef}\n applyRegionColor={applyRegionColor}\n onSegmentPlaybackEnd={onSegmentPlaybackEnd}\n onSegmentClick={handleSegmentClick}\n highlightPlay={highlightPlayButton}\n onPlayStatusNotify={handlePlayStatusNotify}\n lockSegmentSelection={segmentSelectionLocked}\n isSegmentRecorded={isSegmentRecorded}\n allowZoom={true}\n />\n )}\n {bootstrapped && (\n void handleMoreClauses()}\n onFewerClauses={() => void handleFewerClauses()}\n onSplitClause={() => void handleSplitClause()}\n onCombineWithNext={() => void handleCombineWithNext()}\n onUndoCombine={() => void handleUndoCombine()}\n canFewerClauses={!recordingPassStarted}\n canSplitClause={canSplitClause(\n currentIndex,\n clauseRegions,\n recordedClauseIndicesForTools,\n currentClauseSplitPoint\n )}\n canCombineWithNext={canCombineWithNext(\n currentIndex,\n clauseRegions,\n recordedClauseIndicesForTools\n )}\n showUndoCombine={\n combineUndo !== null && !config.multiLevelSegmentUndo\n }\n onStartRecording={handleStartRecording}\n onNextClause={() => void handleNextClause()}\n onClearRecording={() => void handleClearRecording()}\n allClausesHeard={allClausesHeard}\n allClausesComplete={allClausesComplete}\n highlightSpeaker={highlightSpeaker}\n allowRecord={allowRecord && editStep}\n recordBlocked={recordBlocked && phase !== 'recording'}\n savingRecording={savingRecording}\n onSaving={() => {\n savingRecordingRef.current = true;\n setSavingRecording(true);\n }}\n onSaveSettled={() => {\n savingRecordingRef.current = false;\n setSavingRecording(false);\n }}\n toolId={toolId}\n passageId={related(playerMediafile, 'passage') ?? passage?.id}\n artifactId={artifactTypeId}\n sourceMediaId={mediafileId}\n sourceSegments={JSON.stringify(takeRegion ?? {})}\n languagebcp47={stepLanguageField}\n defaultFilename={defaultFilename}\n recordingMediaId={recordingRow?.mediafile?.id}\n afterUploadCb={afterUploadCb}\n onRecording={(active) => {\n if (active) {\n recordingActiveRef.current = true;\n // Latch the take target at record start so later selection\n // changes do not move where this take is filed (TT-7437).\n if (currentRegion) {\n latchRecordingTarget({\n index: currentIndex,\n region: currentRegion,\n });\n }\n // A new take supersedes any earlier rejected save (TT-7583).\n saveRejectedRef.current = false;\n setSaveRejected(false);\n // TT-7552: a deliberate take cancels the post-park overshoot swallow\n // so tapping the next segment is treated as real navigation.\n pendingOvershootSwallowRef.current = false;\n // Recording a take fixes the boundaries around it, so drop the\n // segment-edit undo history — undoing a prior split/combine after a\n // take would restore boundaries the take no longer matches (TT-7666).\n clearSegmentUndo();\n setCombineUndo(null);\n setRecording(true);\n setPhase('recording');\n return;\n }\n const wasRecording = recordingActiveRef.current;\n recordingActiveRef.current = false;\n setRecording(false);\n if (!showRecorder) return;\n if (!wasRecording) {\n savingRecordingRef.current = false;\n setSavingRecording(false);\n return;\n }\n setPhase('recorded');\n }}\n resetMedia={resetMedia}\n setResetMedia={setResetMedia}\n setCanSave={setCanSave}\n onSaveRejected={() => {\n saveRejectedRef.current = true;\n setSaveRejected(true);\n savingRecordingRef.current = false;\n setSavingRecording(false);\n // Upload failures route through afterUploadCb('') as well, but\n // MediaRecord's save-requested-with-no-audio branch only lands here,\n // Also clear optimistic green on this failure path (TT-7583).\n // Keep the latch so Retry still files to the same clause.\n removeOptimistic(\n recordingTargetRef.current?.region ?? currentRegionRef.current\n );\n applyColors();\n }}\n setStatusText={setStatusText}\n showRecorder={showRecorder}\n strings={controlStrings}\n showBoundaryTools={config.showBoundaryTools && editStep}\n readOnly={!editStep}\n controlIdPrefix={config.containerId}\n />\n )}\n {saveRejected ? (\n \n {tm.pendingUploadRetryOne}\n \n }\n >\n {tt.uploadFailed}\n \n ) : (\n statusText && (\n \n {statusText}\n \n )\n )}\n {resetConfirmText && (\n {\n setResetConfirmText(null);\n void performStepBaselineReset();\n }}\n noResponse={() => setResetConfirmText(null)}\n />\n )}\n \n );\n}\n\nexport default PassageDetailGuidedPhraseRecord;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailItem.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getOrgDefault' and 'segments'. Either include them or remove the dependency array.","line":177,"column":6,"nodeType":"ArrayExpression","endLine":177,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, organization, segments]","fix":{"range":[6180,6194],"text":"[getOrgDefault, organization, segments]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'toolChanged'. Either include it or remove the dependency array.","line":188,"column":6,"nodeType":"ArrayExpression","endLine":188,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [canSave, toolChanged]","fix":{"range":[6482,6491],"text":"[canSave, toolChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'fetchMediaUrl'. Either include it or remove the dependency array.","line":193,"column":6,"nodeType":"ArrayExpression","endLine":193,"endColumn":34,"suggestions":[{"desc":"Update the dependencies array to be: [mediafileId, mediaState.id, fetchMediaUrl]","fix":{"range":[6655,6683],"text":"[mediafileId, mediaState.id, fetchMediaUrl]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'segString', 'showMessage', and 't.segmentsChanged'. Either include them or remove the dependency array.","line":220,"column":6,"nodeType":"ArrayExpression","endLine":220,"endColumn":73,"suggestions":[{"desc":"Update the dependencies array to be: [mediafileId, mediafiles, hasBtRecordings, segmentRegion, segments, segString, showMessage, t.segmentsChanged]","fix":{"range":[7795,7862],"text":"[mediafileId, mediafiles, hasBtRecordings, segmentRegion, segments, segString, showMessage, t.segmentsChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'offline', 'plan', and 'recordTypeId'. Either include them or remove the dependency array.","line":257,"column":6,"nodeType":"ArrayExpression","endLine":264,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [memory, passage, rowData, recordType, currentSegmentIndex, currentVersion, plan, recordTypeId, offline]","fix":{"range":[8847,8951],"text":"[memory, passage, rowData, recordType, currentSegmentIndex, currentVersion, plan, recordTypeId, offline]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailLayout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailLwcTranscription.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailLwcTranscription.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setRecording'. Either include it or remove the dependency array.","line":249,"column":6,"nodeType":"ArrayExpression","endLine":249,"endColumn":57,"suggestions":[{"desc":"Update the dependencies array to be: [mediafileId, recordingArtifactTypeId, currentstep, setRecording]","fix":{"range":[7603,7654],"text":"[mediafileId, recordingArtifactTypeId, currentstep, setRecording]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setStepComplete', 'stepComplete', and 'waitForSave'. Either include them or remove the dependency array.","line":272,"column":6,"nodeType":"ArrayExpression","endLine":278,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [allClausesTranscribed, bootstrapped, allRecordingsComplete, hasClauses, currentstep, stepComplete, setStepComplete, waitForSave]","fix":{"range":[8277,8387],"text":"[allClausesTranscribed, bootstrapped, allRecordingsComplete, hasClauses, currentstep, stepComplete, setStepComplete, waitForSave]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailLwcTranslation.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailLwcTranslation.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'startSave'. Either include it or remove the dependency array.","line":263,"column":6,"nodeType":"ArrayExpression","endLine":263,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [canSave, startSave]","fix":{"range":[8200,8209],"text":"[canSave, startSave]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'startSave'. Either include it or remove the dependency array.","line":273,"column":6,"nodeType":"ArrayExpression","endLine":273,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [startSave]","fix":{"range":[8567,8569],"text":"[startSave]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setStepComplete', 'stepComplete', and 'waitForSave'. Either include them or remove the dependency array.","line":339,"column":6,"nodeType":"ArrayExpression","endLine":347,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [allClausesComplete, bootstrapped, allCarefulSpeechComplete, hasClauses, currentstep, savingRecording, stepComplete, setStepComplete, waitForSave]","fix":{"range":[10742,10938],"text":"[allClausesComplete, bootstrapped, allCarefulSpeechComplete, hasClauses, currentstep, savingRecording, stepComplete, setStepComplete, waitForSave]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailMobileDetail.test.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,61],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport React from 'react';\nimport { render } from '@testing-library/react';\n\nconst discussionSize = { width: 450, height: 900 };\nconst mockSetDiscussOpen = jest.fn();\nconst mockUseStepTool = jest.fn();\n\njest.mock('../../context/usePassageDetailContext', () => () => ({\n currentstep: 'step-1',\n section: { id: 's1', type: 'section' },\n discussionSize,\n promptDockedRecordButton: null,\n promptDockedRecordFooterVersion: 0,\n setDiscussOpen: mockSetDiscussOpen,\n}));\n\njest.mock('../../crud', () => {\n const { ToolSlug: Slug, toolAllowsEmptyVernacularAudio } = jest.requireActual<\n typeof import('../../crud/toolSlug')\n >('../../crud/toolSlug');\n return {\n ToolSlug: Slug,\n toolAllowsEmptyVernacularAudio,\n useStepTool: (...args: unknown[]) => mockUseStepTool(...args),\n };\n});\n\njest.mock('../../crud/useRole', () => ({\n useRole: () => ({ userIsAdmin: false }),\n}));\n\njest.mock('../../utils/useStepPermission', () => ({\n useStepPermissions: () => ({\n canDoSectionStep: () => false,\n permissionsOn: false,\n }),\n}));\n\njest.mock('./PassageDetailLayout', () => ({\n __esModule: true,\n default: ({ children }: { children: React.ReactNode }) => (\n
{children}
\n ),\n}));\n\njest.mock('./mobile/MobileWorkflowSteps', () => () => null);\njest.mock('./mobile/PassageDetailMobileFooter', () => () => null);\n\njest.mock('../Discussions/DiscussionPanel', () => ({\n __esModule: true,\n default: () =>
Discussion
,\n}));\n\njest.mock('react-redux', () => ({\n useSelector: (selector: { name?: string }) => {\n if (selector.name === 'sharedSelector') {\n return { noAudio: 'No audio', loadError: 'Error description' };\n }\n },\n shallowEqual: jest.fn(),\n}));\n\nimport { ToolSlug } from '../../crud';\nimport PassageDetailMobileDetail from './PassageDetailMobileDetail';\n\ndescribe('PassageDetailMobileDetail (TT-7373)', () => {\n beforeEach(() => {\n mockSetDiscussOpen.mockClear();\n mockUseStepTool.mockReturnValue({ tool: ToolSlug.Record, settings: {} });\n });\n\n it('uses a fixed discussion column width when side-by-side', () => {\n const { container } = render(\n Waveform
}\n />\n );\n\n expect(\n container.querySelector('[data-cy=\"discussion-side-by-side\"]')\n ).toBeTruthy();\n const column = container.querySelector(\n '[data-cy=\"discussion-side-column\"]'\n ) as HTMLElement;\n expect(column).toBeTruthy();\n expect(container.querySelector('[data-cy=\"record-content\"]')).toBeTruthy();\n expect(\n container.querySelector('[data-cy=\"discussion-panel\"]')\n ).toBeTruthy();\n });\n\n it('stacks discussion below content when not side-by-side', () => {\n const { container } = render(\n Waveform}\n />\n );\n\n expect(\n container.querySelector('[data-cy=\"discussion-side-by-side\"]')\n ).toBeNull();\n expect(container.querySelector('[data-cy=\"record-content\"]')).toBeTruthy();\n expect(\n container.querySelector('[data-cy=\"discussion-panel\"]')\n ).toBeTruthy();\n });\n\n it('does not render discussion-panel for Resource tool (TT-7281)', () => {\n mockUseStepTool.mockReturnValue({ tool: ToolSlug.Resource, settings: {} });\n\n const { container } = render(\n Artifacts}\n />\n );\n\n expect(container.querySelector('[data-cy=\"record-content\"]')).toBeTruthy();\n expect(container.querySelector('[data-cy=\"discussion-panel\"]')).toBeNull();\n expect(mockSetDiscussOpen).toHaveBeenCalledWith(false);\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailMobileDetail.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailParatextIntegration.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'planType'. Either include it or remove the dependency array.","line":48,"column":6,"nodeType":"ArrayExpression","endLine":48,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [plan, planType]","fix":{"range":[1734,1740],"text":"[plan, planType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'memory?.keyMap'. Either include it or remove the dependency array.","line":65,"column":6,"nodeType":"ArrayExpression","endLine":65,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [memory?.keyMap, settings]","fix":{"range":[2192,2202],"text":"[memory?.keyMap, settings]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'slugFromId'. Either include it or remove the dependency array.","line":70,"column":6,"nodeType":"ArrayExpression","endLine":70,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [artifactId, slugFromId]","fix":{"range":[2388,2400],"text":"[artifactId, slugFromId]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailPhraseBackTranslate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailPhraseBackTranslate.undo.test.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":1,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":1,"endColumn":13}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import React from 'react';\nimport { act, cleanup, render, waitFor } from '@testing-library/react';\nimport { IRegion } from '../../crud/useWavesurferRegions';\nimport {\n regionsJsonFromList,\n regionBoundariesEqual,\n} from './carefulSpeech/carefulSpeechBoundary';\nimport { boldDefaultSegParams } from './carefulSpeech/boldCarefulSpeechSegParams';\nimport { phraseBackTranslateConfig } from './guidedPhraseRecord/types';\nimport { ArtifactTypeSlug } from '../../crud/artifactTypeSlug';\nimport { NamedRegions } from '../../utils/namedSegments';\nimport type { IGuidedPhraseRecordControlStrings } from './guidedPhraseRecord/types';\n\n/**\n * Multi-level segment-boundary Undo for Phrase Back Translate (TT-7437).\n *\n * The reported defect: clicking Undo reverts ALL previous boundary edits at\n * once instead of one at a time. The undo stack pops one snapshot, so the fault\n * is on the PUSH side.\n *\n * Verified against the real app (manual log): the failure is NOT caused by fast\n * clicking. Two facts from the waveform make it happen even with seconds\n * between edits:\n *\n * 1. One boundary add fires the segment callback MORE THAN ONCE. Adding a\n * boundary splits a region, and the waveform emits an event for each\n * affected region — two `onSegment` calls (and two saves) per add.\n * 2. The waveform registers that callback ONCE, capturing a STALE closure\n * (the ADR-0006 pattern that `handleRegionPlayEndRef` exists to work\n * around — `onSegment` has no such ref forwarding). So the handler runs\n * with an out-of-date `clauseSegString` and keeps pushing an old snapshot.\n *\n * pushSegmentUndo photographs the closed-over `clauseSegString`\n * ([PassageDetailGuidedPhraseRecord.tsx] pushSegmentUndo). With a stale closure\n * that snapshot is the pre-edit (often the original) segmentation, so the top\n * of the undo stack is the baseline and one Undo reverts everything.\n *\n * These tests model BOTH facts: the waveform's callback is captured once\n * (`captureWaveformCallback`) and each add fires it twice (`addBoundary`). That\n * is why the earlier \"one edit at a time\" test was a FALSE PASS — it re-read a\n * fresh callback per edit and committed between edits, a flow the real app\n * never takes.\n *\n * The current segmentation is observed through the player's `suggestedSegments`\n * prop, which the component feeds from `clauseSegString`.\n */\n\n// ---- segmentations: each \"add\" inserts one more boundary ---------------------\nconst regionsA: IRegion[] = [\n { start: 0, end: 10, label: '' },\n { start: 10, end: 20, label: '' },\n { start: 20, end: 30, label: '' },\n]; // 3 segments — starting point\nconst regionsB: IRegion[] = [\n { start: 0, end: 5, label: '' },\n { start: 5, end: 10, label: '' },\n { start: 10, end: 20, label: '' },\n { start: 20, end: 30, label: '' },\n]; // 4 segments — added a boundary at 5\nconst regionsC: IRegion[] = [\n { start: 0, end: 5, label: '' },\n { start: 5, end: 10, label: '' },\n { start: 10, end: 15, label: '' },\n { start: 15, end: 20, label: '' },\n { start: 20, end: 30, label: '' },\n]; // 5 segments — added a boundary at 15\n\nconst jsonA = regionsJsonFromList(regionsA, boldDefaultSegParams);\nconst jsonB = regionsJsonFromList(regionsB, boldDefaultSegParams);\nconst jsonC = regionsJsonFromList(regionsC, boldDefaultSegParams);\n\n// ---- mutable test state shared with the mocks -------------------------------\nlet playerProps: Record | undefined;\n\nconst stubControls = {\n isReady: jest.fn(() => true),\n isPlaying: jest.fn(() => false),\n gotoTime: jest.fn().mockResolvedValue(undefined),\n setPlay: jest.fn(),\n applyRegionColors: jest.fn(),\n loadRegionsJson: jest.fn(),\n getProgress: jest.fn(() => 0),\n getPlaybackRate: jest.fn(() => 1),\n};\n\nconst ctx: {\n _seg: IRegion | undefined;\n currentSegmentIndex: number;\n [k: string]: unknown;\n} = {\n _seg: regionsA[0],\n currentSegmentIndex: 0,\n currentSegmentSeq: 0,\n passage: { id: 'p1', type: 'passage' },\n playerMediafile: { id: 'm1', type: 'mediafile' },\n mediafileId: 'm1',\n rowData: [],\n currentstep: 'step1',\n section: { id: 's1', type: 'section' },\n setCurrentSegment: jest.fn((region: IRegion) => {\n ctx._seg = region;\n ctx.currentSegmentIndex += 1;\n ctx.currentSegmentSeq = (ctx.currentSegmentSeq as number) + 1;\n }),\n setPlaying: jest.fn(),\n setRecording: jest.fn(),\n forceRefresh: jest.fn(),\n getCurrentSegment: jest.fn(() => ctx._seg),\n isBoldWorkflow: false,\n carefulSpeechSegParams: {},\n setCarefulSpeechSegParams: jest.fn(),\n setStepComplete: jest.fn().mockResolvedValue(undefined),\n stepComplete: jest.fn(() => false),\n};\n\n// ---- mocks ------------------------------------------------------------------\njest.mock('../../context/usePassageDetailContext', () => () => ctx);\n\n// Stateful segments hook: real useState so edits/undo actually re-render, and a\n// stable setter (like the real useState setter) so even a STALE handleSegment\n// closure can still advance the committed state — only its READ of\n// clauseSegString is stale, which is the whole point.\njest.mock('./carefulSpeech/useGuidedPhraseSegments', () => {\n const ReactActual = jest.requireActual('react');\n return {\n useGuidedPhraseSegments: () => {\n const [phraseSegString, setPhraseSegString] = ReactActual.useState(jsonA);\n return {\n phraseSegString,\n setPhraseSegString,\n bootstrapped: true,\n ensureSegments: jest.fn().mockResolvedValue(true),\n resetForScope: jest.fn(),\n resegmentWithParams: jest.fn().mockResolvedValue(false),\n resetToDefaultSegments: jest.fn().mockResolvedValue(false),\n persistPhraseSegments: jest.fn().mockResolvedValue(undefined),\n };\n },\n };\n});\n\njest.mock('./carefulSpeech/carefulSpeechCompletion', () => {\n const actual = jest.requireActual('./carefulSpeech/carefulSpeechCompletion');\n return {\n ...actual,\n getCompletedClauseIndices: jest.fn(() => new Set()),\n getRecordingForClause: jest.fn(() => undefined),\n };\n});\n\njest.mock('../../crud', () => ({\n ArtifactTypeSlug: {\n PhraseBackTranslation: 'phrase-back-translation',\n Vernacular: 'vernacular',\n Retell: 'retell',\n },\n remoteIdGuid: jest.fn((_t: string, id: string) => id),\n useArtifactType: () => ({ getTypeId: () => 'art1', slugFromId: () => 'x' }),\n useStepTool: () => ({\n settings: { artifactTypeId: 'art1', language: 'French|fr' },\n }),\n}));\njest.mock('../../crud/related', () => ({ related: () => 'p1' }));\njest.mock('../../utils/useStepPermission', () => ({\n useStepPermissions: () => ({ canDoSectionStep: () => true }),\n}));\njest.mock('../../crud/isLinkedNote', () => ({ isLinkedNote: () => false }));\njest.mock('../../utils/passageDefaultFilename', () => ({\n passageDefaultFilename: () => 'file.ogg',\n}));\njest.mock('../../selector', () => ({\n sharedSelector: jest.fn(),\n mediaTabSelector: jest.fn(),\n mediaTitleSelector: jest.fn(),\n}));\njest.mock('react-redux', () => ({\n useSelector: () => ({}),\n shallowEqual: jest.fn(),\n}));\njest.mock('../../context/useGlobal', () => ({\n useGlobal: (key: string) =>\n key === 'memory'\n ? [\n { keyMap: {}, update: jest.fn().mockResolvedValue(undefined) },\n jest.fn(),\n ]\n : [undefined, jest.fn()],\n}));\njest.mock('../../context/UnsavedContext', () => {\n const ReactActual = jest.requireActual('react');\n return {\n UnsavedContext: ReactActual.createContext({\n state: {\n startSave: jest.fn(),\n waitForSave: jest.fn().mockResolvedValue(undefined),\n },\n }),\n };\n});\njest.mock('../../hoc/useOrbitData', () => ({\n useOrbitData: () => [\n { id: 'm1', type: 'mediafile', attributes: { versionNumber: 1 } },\n ],\n}));\n\njest.mock('./PassageDetailPlayer', () => ({\n __esModule: true,\n default: (props: Record) => {\n playerProps = props;\n const ref = props.controlsRef as { current: unknown } | undefined;\n if (ref) ref.current = stubControls;\n return
;\n },\n}));\n\njest.mock('./carefulSpeech/CarefulSpeechControls', () => ({\n __esModule: true,\n default: () => {\n return
;\n },\n}));\n\n// imported after the mocks so the component picks them up\nimport { PassageDetailGuidedPhraseRecord } from './PassageDetailGuidedPhraseRecord';\n\nconst config = phraseBackTranslateConfig(\n ArtifactTypeSlug.PhraseBackTranslation,\n NamedRegions.BackTranslation\n);\n\nconst controlStrings: IGuidedPhraseRecordControlStrings = {\n allComplete: 'All recorded',\n unitLabel: 'Segment {0}',\n clearRecording: 'Clear',\n combineWithNext: 'Combine',\n fewerUnits: 'Fewer',\n moreUnits: 'More',\n nextUnit: 'Next',\n splitUnit: 'Split',\n speaker: 'Speaker',\n startRecording: 'Start',\n undo: 'Undo',\n};\n\ntype SegmentCb = (seg: string, init: boolean) => Promise | void;\n\nconst currentSegments = () =>\n playerProps?.suggestedSegments as string | undefined;\n\n// The waveform registers its region listener ONCE and keeps calling that same\n// (stale) callback afterwards — so capture it a single time and reuse it,\n// rather than re-reading the freshest handler each edit.\nconst captureWaveformCallback = (): SegmentCb =>\n playerProps?.onSegment as SegmentCb;\n\n// Model one user \"add a boundary\": the waveform fires the (stale) callback twice\n// for the one gesture (the split emits an event per affected region).\nconst addBoundary = async (cb: SegmentCb, json: string) => {\n await act(async () => {\n await cb(json, false);\n await cb(json, false);\n });\n};\n\nconst fireUndo = async () => {\n const onSegmentUndo = playerProps?.onSegmentUndo as (() => void) | undefined;\n await act(async () => {\n onSegmentUndo?.();\n });\n};\n\nconst mountAndSettle = async () => {\n const utils = render(\n \n );\n await waitFor(() => expect(playerProps).toBeDefined());\n await waitFor(() => expect(currentSegments()).toBeDefined());\n return utils;\n};\n\nbeforeEach(() => {\n playerProps = undefined;\n ctx._seg = regionsA[0];\n ctx.currentSegmentIndex = 0;\n ctx.currentSegmentSeq = 0;\n jest.clearAllMocks();\n stubControls.isReady.mockReturnValue(true);\n stubControls.isPlaying.mockReturnValue(false);\n stubControls.gotoTime.mockResolvedValue(undefined);\n});\n\nafterEach(() => cleanup());\n\ndescribe('Phrase Back Translate — multi-level segment Undo (TT-7437)', () => {\n it('has multi-level undo enabled for this step', () => {\n expect(config.multiLevelSegmentUndo).toBe(true);\n });\n\n // The manual repro, faithfully: two boundary adds, spaced out, then one Undo.\n // Each add is delivered through the waveform's single captured callback and\n // fires twice. Undo must step back exactly ONE add.\n it('undoes ONE add per click (matches the manual repro)', async () => {\n await mountAndSettle();\n const waveform = captureWaveformCallback();\n expect(regionBoundariesEqual(currentSegments()!, jsonA)).toBe(true);\n\n await addBoundary(waveform, jsonB);\n expect(regionBoundariesEqual(currentSegments()!, jsonB)).toBe(true);\n\n await addBoundary(waveform, jsonC);\n expect(regionBoundariesEqual(currentSegments()!, jsonC)).toBe(true);\n\n // First Undo: back to B (remove only the last boundary), NOT all the way to A.\n await fireUndo();\n expect(regionBoundariesEqual(currentSegments()!, jsonB)).toBe(true);\n\n // Second Undo: back to A.\n await fireUndo();\n expect(regionBoundariesEqual(currentSegments()!, jsonA)).toBe(true);\n });\n\n // Isolates fact #1: a single add fires the callback twice, so it must record\n // only ONE undo entry. Observing state alone can't see the extra entry (both\n // duplicates are the same snapshot), so assert the button disables after one\n // Undo — the extra entry keeps it enabled.\n it('records ONE undo entry for a single add even though it fires twice', async () => {\n await mountAndSettle();\n const waveform = captureWaveformCallback();\n\n await addBoundary(waveform, jsonB); // one gesture, two callback fires\n expect(playerProps?.hasSegmentUndo).toBe(true);\n\n await fireUndo();\n expect(regionBoundariesEqual(currentSegments()!, jsonA)).toBe(true);\n // Exactly one add was made, so after one Undo there must be nothing left.\n expect(playerProps?.hasSegmentUndo).toBe(false);\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailPlayer.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setPlayerSegments' and 'setupLocate'. Either include them or remove the dependency array.","line":426,"column":6,"nodeType":"ArrayExpression","endLine":426,"endColumn":33,"suggestions":[{"desc":"Update the dependencies array to be: [currentstep, allowSegment, setupLocate, setPlayerSegments]","fix":{"range":[14196,14223],"text":"[currentstep, allowSegment, setupLocate, setPlayerSegments]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearCompleted', 'clearRequested', 'saveRequested', and 'writeSegments'. Either include them or remove the dependency array.","line":434,"column":6,"nodeType":"ArrayExpression","endLine":434,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [clearCompleted, clearRequested, saveRequested, toolsChanged, writeSegments]","fix":{"range":[14457,14471],"text":"[clearCompleted, clearRequested, saveRequested, toolsChanged, writeSegments]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailRecord.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailRecord.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":144,"column":6,"nodeType":"ArrayExpression","endLine":144,"endColumn":76,"suggestions":[{"desc":"Update the dependencies array to be: [getSharedResource, passage, plan, memory, offline, toolSettings, allBookData]","fix":{"range":[4911,4981],"text":"[getSharedResource, passage, plan, memory, offline, toolSettings, allBookData]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'toolChanged'. Either include it or remove the dependency array.","line":156,"column":6,"nodeType":"ArrayExpression","endLine":156,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [canSave, toolChanged]","fix":{"range":[5245,5254],"text":"[canSave, toolChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearCompleted', 'clearRequested', 'handleSave', and 'saveRequested'. Either include them or remove the dependency array.","line":164,"column":6,"nodeType":"ArrayExpression","endLine":164,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [clearCompleted, clearRequested, handleSave, saveRequested, toolsChanged]","fix":{"range":[5463,5477],"text":"[clearCompleted, clearRequested, handleSave, saveRequested, toolsChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchMediaUrl' and 'mediaState.id'. Either include them or remove the dependency array.","line":173,"column":6,"nodeType":"ArrayExpression","endLine":173,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [fetchMediaUrl, mediaState.id, mediafileId, passage]","fix":{"range":[5754,5776],"text":"[fetchMediaUrl, mediaState.id, mediafileId, passage]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has an unnecessary dependency: 'mediafiles'. Either exclude it or remove the dependency array.","line":180,"column":6,"nodeType":"ArrayExpression","endLine":180,"endColumn":39,"suggestions":[{"desc":"Update the dependencies array to be: [memory, mediafileId]","fix":{"range":[6037,6070],"text":"[memory, mediafileId]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailStepComplete.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":2,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":2,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailStepComplete.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'stepComplete'. Either include it or remove the dependency array.","line":76,"column":5,"nodeType":"ArrayExpression","endLine":76,"endColumn":32,"suggestions":[{"desc":"Update the dependencies array to be: [currentstep, stepComplete]","fix":{"range":[2814,2841],"text":"[currentstep, stepComplete]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'passageNavigate' and 'pathname'. Either include them or remove the dependency array.","line":120,"column":6,"nodeType":"ArrayExpression","endLine":120,"endColumn":36,"suggestions":[{"desc":"Update the dependencies array to be: [view, busy, importexportBusy, pathname, passageNavigate]","fix":{"range":[3896,3926],"text":"[view, busy, importexportBusy, pathname, passageNavigate]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'view'. Either include it or remove the dependency array.","line":125,"column":6,"nodeType":"ArrayExpression","endLine":125,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [pathname, view]","fix":{"range":[4042,4052],"text":"[pathname, view]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailTranscribe.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\PassageDetailTranscribe.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'localizedArtifactTypeFromId'. Either include it or remove the dependency array.","line":308,"column":6,"nodeType":"ArrayExpression","endLine":308,"endColumn":63,"suggestions":[{"desc":"Update the dependencies array to be: [artifactTypeId, localizedArtifactTypeFromId, rowData, mediafileId, stepLanguageBcp47]","fix":{"range":[10157,10214],"text":"[artifactTypeId, localizedArtifactTypeFromId, rowData, mediafileId, stepLanguageBcp47]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Prompt\\PassageDetailPrompt.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Prompt\\PassageDetailPromptAdmin.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'toolChanged'. Either include it or remove the dependency array.","line":108,"column":6,"nodeType":"ArrayExpression","endLine":108,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [canSave, toolChanged]","fix":{"range":[3614,3623],"text":"[canSave, toolChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'DeleteSectionResource', 'clearCompleted', 'clearRequested', and 'forceRefresh'. Either include them or remove the dependency array.","line":123,"column":6,"nodeType":"ArrayExpression","endLine":123,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [DeleteSectionResource, clearCompleted, clearRequested, forceRefresh, toolsChanged]","fix":{"range":[3992,4006],"text":"[DeleteSectionResource, clearCompleted, clearRequested, forceRefresh, toolsChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Prompt\\PassageDetailPromptMember.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Prompt\\promptPendingRestore.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Prompt\\promptPendingRestore.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Prompt\\usePromptSectionResource.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\Prompt\\usePromptSectionResource.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\RecordButtons.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\SaveSegments.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\SelectRecording.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":146,"column":5,"severity":1,"nodeType":null,"fix":{"range":[4229,4284],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import {\n Paper,\n Table,\n TableBody,\n TableCell,\n TableCellProps,\n TableContainer,\n TableHead,\n TableRow,\n Box,\n styled,\n} from '@mui/material';\nimport BigDialog from '../../hoc/BigDialog';\nimport { useContext, useEffect, useState, useMemo } from 'react';\nimport { ISelectRecordingStrings, IState } from '../../model';\nimport { IRow, PassageDetailContext } from '../../context/PassageDetailContext';\nimport { ArtifactTypeSlug, useArtifactType } from '../../crud';\nimport { dateOrTime, prettySegment, removeExtension } from '../../utils';\nimport { ItemDescription } from '../../control/MediaDescription';\nimport { selectRecordingSelector } from '../../selector';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport { Button } from '../../control/Button';\n\ninterface StyledCellProps extends TableCellProps {\n old?: boolean;\n}\nconst StyledCell = styled(TableCell, {\n shouldForwardProp: (prop) => prop !== 'old',\n})(({ old, theme }) => ({\n ...(old && {\n color: theme.palette.secondary.light,\n }),\n}));\n\ninterface IHeaderProps {\n showTopic: boolean;\n showType: boolean;\n}\n\nconst RecordingHeader = ({ showTopic, showType }: IHeaderProps) => {\n const t: ISelectRecordingStrings = useSelector(\n selectRecordingSelector,\n shallowEqual\n );\n return (\n \n {showType && {t.artifactType}}\n {t.sourceVersion}\n {t.sourceSegment}\n {showTopic && {t.topic}}\n {t.created}\n {t.speaker}\n {t.filename}\n \n );\n};\n\ninterface IInfoProps {\n row: IRow;\n lang: string;\n onClick: (id: string, latest: boolean) => () => void;\n latestVernacular: number;\n showTopic: boolean;\n showType: boolean;\n}\n\nconst RecordingInfo = (iprops: IInfoProps) => {\n const { row, lang, onClick, latestVernacular, showTopic, showType } = iprops;\n\n return (\n \n {showType && (\n \n {row.artifactType}\n \n )}\n \n {row.sourceVersion}\n \n \n {prettySegment(row.mediafile.attributes?.sourceSegments || '')}\n \n {showTopic && (\n {row.mediafile.attributes?.topic}\n )}\n \n {dateOrTime(row.mediafile.attributes?.dateCreated, lang)}\n \n \n {row.mediafile.attributes?.performedBy}\n \n \n {removeExtension(row.artifactName).name}\n \n \n );\n};\n\ninterface IProps {\n inItem?: string;\n label?: string;\n onChange?: (resource: string, latest: boolean) => void;\n required?: boolean;\n tags: string[];\n latestVernacular: number;\n}\nexport const SelectRecording = (props: IProps) => {\n const { onChange, inItem, tags, latestVernacular } = props;\n const lang = useSelector((state: IState) => state.strings.lang);\n const ctx = useContext(PassageDetailContext);\n const { rowData } = ctx.state;\n const [item, setItem] = useState('');\n const [chooser, setChooser] = useState(false);\n const { localizedArtifactType } = useArtifactType();\n const t: ISelectRecordingStrings = useSelector(\n selectRecordingSelector,\n shallowEqual\n );\n\n const showTopic = useMemo(() => {\n return (\n tags[0] !== ArtifactTypeSlug.WholeBackTranslation &&\n tags[0] !== ArtifactTypeSlug.PhraseBackTranslation\n );\n }, [tags]);\n\n const showType = useMemo(() => {\n return tags.length > 1;\n }, [tags]);\n\n const handleClick = (id: string, latest: boolean) => () => {\n setItem(id);\n onChange && onChange(id, latest);\n setChooser(false);\n };\n\n const handleItem = () => {\n setChooser(true);\n };\n\n useEffect(() => {\n if (inItem) setItem(inItem);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [inItem]);\n\n const localTags = useMemo(() => {\n return tags.map((t) => localizedArtifactType(t));\n }, [tags, localizedArtifactType]);\n return (\n <>\n \n \n r.id === item)?.mediafile}\n />\n \n {chooser && (\n \n \n \n \n \n \n \n {rowData\n .filter((r) => localTags.includes(r.artifactType))\n .sort((i, j) =>\n parseFloat(\n prettySegment(\n i?.mediafile?.attributes?.sourceSegments ?? '{}'\n )\n ) <\n parseFloat(\n prettySegment(\n j?.mediafile?.attributes?.sourceSegments ?? '{}'\n )\n )\n ? -1\n : parseFloat(\n prettySegment(\n i?.mediafile?.attributes?.sourceSegments ?? '{}'\n )\n ) >\n parseFloat(\n prettySegment(\n j?.mediafile?.attributes?.sourceSegments ?? '{}'\n )\n )\n ? 1\n : i.artifactType < j.artifactType\n ? -1\n : i.artifactType > j.artifactType\n ? 1\n : i.sourceVersion === j.sourceVersion\n ? i.artifactName <= j.artifactName\n ? -1\n : 1\n : j.sourceVersion - i.sourceVersion\n )\n .map((r) => (\n \n ))}\n \n
\n
\n \n )}\n \n );\n};\nexport default SelectRecording;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\StepNavigationConfirmDialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\TeamCheckReference.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":40,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":40,"endColumn":13,"suppressions":[{"kind":"directive","justification":"JSX (react-jsx) still expects React in scope for TS in this file"}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\TeamCheckReference.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'SecSlug', 'handleResource', 'setPlayItem', and 'storeKey'. Either include them or remove the dependency array.","line":85,"column":6,"nodeType":"ArrayExpression","endLine":85,"endColumn":37,"suggestions":[{"desc":"Update the dependencies array to be: [section, passage, currentstep, setPlayItem, storeKey, SecSlug, handleResource]","fix":{"range":[2626,2657],"text":"[section, passage, currentstep, setPlayItem, storeKey, SecSlug, handleResource]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\WorkflowSteps.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":55,"column":5,"severity":1,"nodeType":null,"fix":{"range":[1618,1673],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'nextWF', 'prevWF', 'setFirstStepIndex', and 'stageWdith'. Either include them or remove the dependency array.","line":81,"column":6,"nodeType":"ArrayExpression","endLine":81,"endColumn":52,"suggestions":[{"desc":"Update the dependencies array to be: [currentstep, firstStepIndex, workflow, width, stageWdith, prevWF, nextWF, setFirstStepIndex]","fix":{"range":[2713,2759],"text":"[currentstep, firstStepIndex, workflow, width, stageWdith, prevWF, nextWF, setFirstStepIndex]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { Box, debounce, useTheme } from '@mui/material';\nimport { Stage } from '../../control/Stage';\nimport usePassageDetailContext from '../../context/usePassageDetailContext';\nimport { useEffect, useState } from 'react';\nimport { SimpleWf } from '../../context/PassageDetailContext';\nimport { useGetGlobal } from '../../context/useGlobal';\nimport { useSnackBar } from '../../hoc/SnackBar';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport { sharedSelector } from '../../selector';\nimport { useWfLabel } from '../../utils/useWfLabel';\n\nexport function WorkflowSteps() {\n const {\n workflow,\n stepComplete,\n currentstep,\n setCurrentStep,\n firstStepIndex,\n setFirstStepIndex,\n recording,\n commentRecording,\n } = usePassageDetailContext();\n const theme = useTheme();\n const [shownWorkflow, setShownWorkflow] = useState([]);\n const [width, setWidth] = useState(0);\n const [stageWdith, setStageWidth] = useState(300);\n const { showMessage } = useSnackBar();\n const ts = useSelector(sharedSelector, shallowEqual);\n const getWfLabel = useWfLabel();\n const getGlobal = useGetGlobal();\n const prevWF = {\n id: 'prev',\n label: '<<',\n };\n const nextWF = {\n id: 'next',\n label: '>>',\n };\n\n // keep track of screen width\n const setDimensions = () => {\n setWidth(window.innerWidth);\n };\n\n useEffect(() => {\n setDimensions();\n const handleResize = debounce(() => {\n setDimensions();\n }, 100);\n\n window.addEventListener('resize', handleResize);\n return () => {\n window.removeEventListener('resize', handleResize);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []); //do this once to get the default;\n\n useEffect(() => {\n const show = Math.ceil(width / 200);\n // 24 for next/prev icon + 16 padding with 10 padding on bar = 100\n const newStageWdith = (width - 100) / show;\n if (newStageWdith !== stageWdith) setStageWidth(newStageWdith);\n if (!workflow || !workflow.length) return;\n let tempFirstStep = firstStepIndex;\n if (firstStepIndex < 0) {\n if (currentstep) {\n const stepIndex = workflow.findIndex((w) => w.id === currentstep);\n tempFirstStep = Math.floor(Math.max(stepIndex - show / 2, 0));\n } else tempFirstStep = 0;\n setFirstStepIndex(tempFirstStep);\n }\n let wf: SimpleWf[] = [];\n wf.push({ ...prevWF, label: tempFirstStep > 0 ? prevWF.label : '' });\n wf = wf.concat(workflow.slice(tempFirstStep, tempFirstStep + show));\n wf.push({\n ...nextWF,\n label: tempFirstStep + show < workflow.length ? nextWF.label : '',\n });\n setShownWorkflow(wf);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentstep, firstStepIndex, workflow, width]);\n\n const curColor = (id: string) => {\n return id === currentstep\n ? theme.palette.secondary.light\n : stepComplete(id)\n ? theme.palette.grey[300]\n : undefined;\n };\n\n const handleSelect = (item: string) => {\n if (recording || commentRecording) return;\n if (getGlobal('remoteBusy')) {\n showMessage(ts.wait);\n return;\n }\n if (item === currentstep) {\n //do nothing;\n } else {\n setCurrentStep(item);\n }\n };\n const moveStep = (forward: boolean) => {\n if (forward)\n setFirstStepIndex(Math.min(workflow.length - 1, firstStepIndex + 1));\n else setFirstStepIndex(Math.max(0, firstStepIndex - 1));\n };\n return (\n \n {shownWorkflow.map((w) => (\n \n ))}\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\boldClauseTranscription.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\boldClauseTranscription.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\boldClause\\BoldClauseNav.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\boldClause\\ClauseAudioPlayer.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchMediaUrl', 'showMessage', 'ts.mediaError', and 'waitLabel'. Either include them or remove the dependency array.","line":115,"column":6,"nodeType":"ArrayExpression","endLine":115,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [fetchMediaUrl, mediaId, showMessage, ts.mediaError, waitLabel]","fix":{"range":[3224,3233],"text":"[fetchMediaUrl, mediaId, showMessage, ts.mediaError, waitLabel]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\boldClause\\ClauseProgress.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\boldClause\\ClauseProgress.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\boldClause\\StepMessage.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\boldDesktopStepComplete.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\boldDesktopStepComplete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\boldLwcTranscription.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\btDefaultSegParams.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\CarefulSpeechControls.test.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,61],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport React from 'react';\nimport { describe, expect, it, afterEach, jest } from '@jest/globals';\nimport { cleanup, render } from '@testing-library/react';\n\n// MediaRecord pulls PassageDetailContext + WSAudioPlayer; stub it so we can\n// render the recorder section (which contains the Next Clause button) in\n// isolation. The CT (CarefulSpeechControls.cy.tsx) covers the listen-pass\n// buttons that live outside the showRecorder block.\njest.mock('../../MediaRecord', () => ({\n __esModule: true,\n default: () =>
,\n}));\n\n// The control barrel transitively imports react-localization (ESM) and fails\n// to parse under jest; we only need Button here.\njest.mock('../../../control', () => ({\n Button: ({\n children,\n id,\n onClick,\n disabled,\n }: {\n children: React.ReactNode;\n id?: string;\n onClick?: () => void;\n disabled?: boolean;\n }) => (\n \n ),\n}));\n\nimport CarefulSpeechControls from './CarefulSpeechControls';\n\nconst controlStrings = {\n allComplete: 'All clauses are complete.',\n unitLabel: 'Clause: {0}',\n clearRecording: 'Clear Recording',\n combineWithNext: 'Combine with Next Clause',\n fewerUnits: 'Fewer Clauses',\n moreUnits: 'More Clauses',\n nextUnit: 'Next Clause',\n splitUnit: 'Split Clause',\n speaker: 'Speaker',\n startRecording: 'Start Recording',\n undo: 'Undo',\n};\n\nconst baseProps: React.ComponentProps = {\n width: 360,\n phase: 'recorded',\n recordingPassStarted: true,\n currentRegion: { start: 0, end: 10, label: '' },\n speaker: 'Greg',\n onSpeakerChange: () => {},\n onMoreClauses: () => {},\n onFewerClauses: () => {},\n onCombineWithNext: () => {},\n onSplitClause: () => {},\n onUndoCombine: () => {},\n canFewerClauses: false,\n canCombineWithNext: false,\n canSplitClause: false,\n showUndoCombine: false,\n onStartRecording: () => {},\n onNextClause: () => {},\n onClearRecording: () => {},\n allClausesHeard: false,\n allClausesComplete: false,\n highlightSpeaker: false,\n allowRecord: false,\n toolId: 'CarefulSpeechTool',\n passageId: 'p1',\n artifactId: 'art1',\n sourceMediaId: 'mf1',\n sourceSegments: '{}',\n defaultFilename: 'test.ogg',\n afterUploadCb: async () => {},\n onRecording: () => {},\n resetMedia: false,\n setResetMedia: () => {},\n setCanSave: () => {},\n setStatusText: () => {},\n showRecorder: true,\n strings: controlStrings,\n showBoundaryTools: true,\n};\n\nafterEach(() => {\n cleanup();\n jest.clearAllMocks();\n});\n\ndescribe('CarefulSpeechControls — Next Clause completion state', () => {\n it('Next Clause is enabled while clauses remain to record', () => {\n const { container } = render(\n \n );\n const next = container.querySelector(\n '#careful-speech-next'\n ) as HTMLButtonElement | null;\n expect(next).toBeTruthy();\n expect(next?.disabled).toBe(false);\n });\n\n it('Next Clause is disabled once every clause is recorded', () => {\n const { container } = render(\n \n );\n const next = container.querySelector(\n '#careful-speech-next'\n ) as HTMLButtonElement | null;\n expect(next).toBeTruthy();\n expect(next?.disabled).toBe(true);\n });\n\n it('Next Clause is disabled while the recording upload is in progress', () => {\n const { container } = render(\n \n );\n const next = container.querySelector(\n '#careful-speech-next'\n ) as HTMLButtonElement | null;\n expect(next).toBeTruthy();\n expect(next?.disabled).toBe(true);\n });\n\n it('Combine with Next Clause is disabled while the recording upload is in progress', () => {\n const { container } = render(\n \n );\n const combine = container.querySelector(\n '#careful-speech-combine'\n ) as HTMLButtonElement | null;\n expect(combine).toBeTruthy();\n expect(combine?.disabled).toBe(true);\n });\n\n it('Split Clause is disabled while the recording upload is in progress', () => {\n const { container } = render(\n \n );\n const split = container.querySelector(\n '#careful-speech-split'\n ) as HTMLButtonElement | null;\n expect(split).toBeTruthy();\n expect(split?.disabled).toBe(true);\n });\n\n it('Undo Combine is disabled while the recording upload is in progress', () => {\n const { container } = render(\n \n );\n const undo = container.querySelector(\n '#careful-speech-undo-combine'\n ) as HTMLButtonElement | null;\n expect(undo).toBeTruthy();\n expect(undo?.disabled).toBe(true);\n });\n});\n\ndescribe('CarefulSpeechControls linked note play-only (TT-5873)', () => {\n it('keeps playback while hiding record and edit controls', () => {\n const { container, queryByLabelText, queryByText } = render(\n \n );\n expect(\n container.querySelector('[data-testid=\"media-record\"]')\n ).toBeTruthy();\n expect(queryByText('Start Recording')).toBeNull();\n expect(queryByLabelText('Clear Recording')).toBeNull();\n const speaker = container.querySelector(\n '#careful-speech-speaker'\n ) as HTMLInputElement | null;\n expect(speaker).toBeTruthy();\n expect(speaker?.disabled).toBe(true);\n });\n\n it('hides Start Recording when read-only', () => {\n const { queryByText } = render(\n \n );\n expect(queryByText('Start Recording')).toBeNull();\n });\n\n it('still allows recording on an owned note', () => {\n const { queryByText } = render(\n \n );\n expect(queryByText(/Start Recording/)).toBeTruthy();\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\CarefulSpeechControls.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\boldCarefulSpeechSegParams.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\boldCarefulSpeechSegParams.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\carefulSpeechBoundary.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\carefulSpeechBoundary.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\carefulSpeechClauseMerge.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\carefulSpeechClauseMerge.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\carefulSpeechClauseSplit.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\carefulSpeechClauseSplit.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\carefulSpeechCompletion.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\carefulSpeechCompletion.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\carefulSpeechFormat.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\claimLegacyPhraseBt.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\claimLegacyPhraseBt.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\matchesGuidedOutputRow.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\matchesGuidedOutputRow.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\resolveSegmentSpeaker.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\resolveSegmentSpeaker.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\useCarefulSpeechSegments.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\useGuidedPhraseSegments.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\carefulSpeech\\useGuidedPhraseSegments.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\guidedPhraseRecord\\controlStrings.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\guidedPhraseRecord\\types.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\guidedPhraseRecord\\types.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranscription\\BoldClauseTranscriptionEditor.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'getName'. Either include it or remove the dependency array.","line":186,"column":6,"nodeType":"ArrayExpression","endLine":186,"endColumn":58,"suggestions":[{"desc":"Update the dependencies array to be: [asrSettings?.language?.bcp47, asrSettings?.language?.languageName, getName, stepSettings, tPlayer.recognizeSpeech]","fix":{"range":[6671,6723],"text":"[asrSettings?.language?.bcp47, asrSettings?.language?.languageName, getName, stepSettings, tPlayer.recognizeSpeech]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranscription\\LwcTranscriptionEditor.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranscription\\LwcTranscriptionEditor.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranscription\\lwcTranscriptionCompletion.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranscription\\lwcTranscriptionCompletion.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranscription\\useTranscriptionAutosave.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranscription\\useTranscriptionAutosave.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranslation\\LwcTranslationClauseNav.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranslation\\LwcTranslationClauseNav.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranslation\\LwcTranslationControls.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranslation\\LwcTranslationControls.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranslation\\LwcTranslationReferencePlayer.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\lwcTranslation\\useLwcTranslationClauses.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\markVersesTool.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\MarkVerses\\EditReferenceDropdown.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\MarkVerses\\EditReferenceDropdown.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\MarkVerses\\MarkVersesTable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\MarkVerses\\PassageDetailMarkVerses.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\MarkVerses\\PassageDetailMarkVerses.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'emptyTable', 'media', 'resetLoadedVerseMarkings', 'setCurrentSegment', 'setData', and 'setupData'. Either include them or remove the dependency array.","line":483,"column":6,"nodeType":"ArrayExpression","endLine":483,"endColumn":42,"suggestions":[{"desc":"Update the dependencies array to be: [emptyTable, getPassageRefs, media, passage, passageId, resetLoadedVerseMarkings, setCurrentSegment, setData, setupData]","fix":{"range":[17644,17680],"text":"[emptyTable, getPassageRefs, media, passage, passageId, resetLoadedVerseMarkings, setCurrentSegment, setData, setupData]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearCompleted', 'clearRequested', and 'saveRequested'. Either include them or remove the dependency array.","line":1498,"column":6,"nodeType":"ArrayExpression","endLine":1498,"endColumn":38,"suggestions":[{"desc":"Update the dependencies array to be: [toolsChanged, scheduleAutosave, saveRequested, clearRequested, clearCompleted]","fix":{"range":[52049,52081],"text":"[toolsChanged, scheduleAutosave, saveRequested, clearRequested, clearCompleted]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'tableSignature'. Either include it or remove the dependency array.","line":1536,"column":6,"nodeType":"ArrayExpression","endLine":1536,"endColumn":53,"suggestions":[{"desc":"Update the dependencies array to be: [emptyTable, getPassageRefs, passage, tableSignature, rowCells]","fix":{"range":[52979,53026],"text":"[emptyTable, getPassageRefs, passage, tableSignature, rowCells]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'tableSignature'. Either include it or remove the dependency array.","line":1541,"column":5,"nodeType":"ArrayExpression","endLine":1541,"endColumn":48,"suggestions":[{"desc":"Update the dependencies array to be: [numSegments, tableSignature, data, pristineTableSignature]","fix":{"range":[53210,53253],"text":"[numSegments, tableSignature, data, pristineTableSignature]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\MobileStepComplete.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'stepComplete'. Either include it or remove the dependency array.","line":48,"column":5,"nodeType":"ArrayExpression","endLine":48,"endColumn":32,"suggestions":[{"desc":"Update the dependencies array to be: [currentstep, stepComplete]","fix":{"range":[1878,1905],"text":"[currentstep, stepComplete]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\MobileWorkflowSteps.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\PassageDetailMobileContext.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\PassageDetailMobileFooter.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\SegmentStatusMobile.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\TeamCheckReferenceMobile.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":62,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":62,"endColumn":13,"suppressions":[{"kind":"directive","justification":"JSX (react-jsx) still expects React in scope for TS in this file"}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\TeamCheckReferenceMobile.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'SecSlug', 'handleResource', 'setPlayItem', and 'storeKey'. Either include them or remove the dependency array.","line":132,"column":6,"nodeType":"ArrayExpression","endLine":132,"endColumn":37,"suggestions":[{"desc":"Update the dependencies array to be: [section, passage, currentstep, setPlayItem, storeKey, SecSlug, handleResource]","fix":{"range":[3653,3684],"text":"[section, passage, currentstep, setPlayItem, storeKey, SecSlug, handleResource]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\record\\AudioVersionCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\record\\ProvideRightsMobile.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\mobile\\transcribe\\PassageDetailTranscribeMobile.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'mediafile'. Either include it or remove the dependency array.","line":519,"column":6,"nodeType":"ArrayExpression","endLine":524,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [mediafile?.id, mediafile?.attributes?.transcription, textValue, actions.savingRef, mediafile]","fix":{"range":[16122,16226],"text":"[mediafile?.id, mediafile?.attributes?.transcription, textValue, actions.savingRef, mediafile]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'actions', 'clearCompleted', 'clearRequested', 'currentstep', and 'saveRequested'. Either include them or remove the dependency array.","line":736,"column":6,"nodeType":"ArrayExpression","endLine":736,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [actions, clearCompleted, clearRequested, currentstep, saveRequested, toolsChanged]","fix":{"range":[22673,22687],"text":"[actions, clearCompleted, clearRequested, currentstep, saveRequested, toolsChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\phraseSegmentRecordingComplete.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\phraseSegmentRecordingComplete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\transcribeDefaultSegParams.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\transcribe\\useTranscribeActions.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\transcribe\\useTranscribeActions.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\transcribe\\useTranscribeAsr.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageDetail\\usePassageNavigate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageHistory.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'activityStateStr', 'getUserRec', 'handleDelete', 'handleMouseLeave', 'locale', 'memory?.keyMap', 'props', and 'user'. Either include them or remove the dependency array.","line":180,"column":6,"nodeType":"ArrayExpression","endLine":180,"endColumn":35,"suggestions":[{"desc":"Update the dependencies array to be: [activityStateStr, curStateChanges, getUserRec, handleDelete, handleMouseLeave, locale, memory?.keyMap, props, selectedId, user]","fix":{"range":[5864,5893],"text":"[activityStateStr, curStateChanges, getUserRec, handleDelete, handleMouseLeave, locale, memory?.keyMap, props, selectedId, user]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageRecordDlg.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PassageRecordDlg.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'speaker'. Either include it or remove the dependency array.","line":198,"column":6,"nodeType":"ArrayExpression","endLine":198,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [mode, speaker]","fix":{"range":[6522,6528],"text":"[mode, speaker]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchMediaUrl' and 'mediaState.id'. Either include them or remove the dependency array.","line":205,"column":6,"nodeType":"ArrayExpression","endLine":205,"endColumn":21,"suggestions":[{"desc":"Update the dependencies array to be: [mode, mediaId, mediaState.id, fetchMediaUrl]","fix":{"range":[6719,6734],"text":"[mode, mediaId, mediaState.id, fetchMediaUrl]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Peers\\GroupDialog.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has a missing dependency: 'localizedPermissions'. Either include it or remove the dependency array.","line":118,"column":5,"nodeType":"ArrayExpression","endLine":118,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [localizedPermissions]","fix":{"range":[3333,3346],"text":"[localizedPermissions]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'getPermissionFromJson', 'inUseSchemes', 'inUseSteps', 'name', 'orgSchemeSteps', and 'permissions'. Either include them or remove the dependency array.","line":146,"column":6,"nodeType":"ArrayExpression","endLine":146,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [cur, getPermissionFromJson, inUseSchemes, inUseSteps, name, orgSchemeSteps, permissions]","fix":{"range":[4182,4187],"text":"[cur, getPermissionFromJson, inUseSchemes, inUseSteps, name, orgSchemeSteps, permissions]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'getPermissionFromJson'. Either include it or remove the dependency array.","line":153,"column":5,"nodeType":"ArrayExpression","endLine":153,"endColumn":29,"suggestions":[{"desc":"Update the dependencies array to be: [name, cur?.attributes.name, cur?.attributes.permissions, permissions, getPermissionFromJson]","fix":{"range":[4413,4437],"text":"[name, cur?.attributes.name, cur?.attributes.permissions, permissions, getPermissionFromJson]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Peers\\Peer.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":145,"column":5,"severity":1,"nodeType":null,"fix":{"range":[4350,4405],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'getMyOrgRole'. Either include it or remove the dependency array.","line":140,"column":5,"nodeType":"ArrayExpression","endLine":140,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [getMyOrgRole, organization, offline]","fix":{"range":[4212,4235],"text":"[getMyOrgRole, organization, offline]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { useMemo } from 'react';\nimport { useGlobal } from '../../context/useGlobal';\nimport {\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Paper,\n IconButton,\n} from '@mui/material';\nimport UncheckedIcon from '@mui/icons-material/CheckBoxOutlineBlank';\nimport CheckedIcon from '@mui/icons-material/CheckBoxOutlined';\nimport GroupDialog from './GroupDialog';\nimport {\n GroupMembership,\n Group,\n GroupD,\n RoleNames,\n IPeerStrings,\n GroupMembershipD,\n} from '../../model';\nimport { related, usePermissions, useRole } from '../../crud';\nimport { AddRecord, ReplaceRelatedRecord } from '../../model/baseModel';\nimport { toCamel } from '../../utils';\nimport { useSelector, shallowEqual } from 'react-redux';\nimport { peerSelector } from '../../selector';\nimport { usePeerGroups, IUserName } from './usePeerGroups';\nimport { InitializedRecord } from '@orbit/records';\nimport { useOrbitData } from '../../hoc/useOrbitData';\n\nexport function Peer() {\n const memberships = useOrbitData('groupmembership');\n const [memory] = useGlobal('memory');\n const [offline] = useGlobal('offline'); //verified this is not used in a function 2/18/25\n const [user] = useGlobal('user');\n const [organization] = useGlobal('organization');\n const { userNames, peerGroups, check, cAdd, cDelete, cKey } = usePeerGroups();\n const { getRoleId, getMyOrgRole } = useRole();\n const t = useSelector(peerSelector, shallowEqual) as IPeerStrings;\n const { localizePermission } = usePermissions();\n\n const handleSave = async (name: string, permissions: string, id?: string) => {\n if (id) {\n // update peer group\n for (const g of peerGroups) {\n if (g.id === id) {\n await memory.update((t) => t.replaceAttribute(g, 'name', name));\n await memory.update((t) =>\n t.replaceAttribute(\n g,\n 'permissions',\n JSON.stringify({ permissions: permissions })\n )\n );\n return;\n }\n }\n return;\n }\n // create peer group\n const groupRec: Group = {\n type: 'group',\n attributes: {\n name,\n abbreviation: toCamel(name),\n allUsers: false,\n permissions: JSON.stringify({ permissions: permissions }),\n },\n } as Group;\n await memory.update((t) => [\n ...AddRecord(t, groupRec, user, memory),\n ...ReplaceRelatedRecord(\n t,\n groupRec as GroupD,\n 'owner',\n 'organization',\n organization\n ),\n ]);\n };\n\n const handleRemove = async (id: string) => {\n // remove all group memberships\n await memory.update((t) =>\n memberships\n .filter((m) => related(m, 'group') === id)\n .map((m) => t.removeRecord(m))\n );\n // remove group\n await memory.update((t) => t.removeRecord({ type: 'group', id }));\n };\n\n const handleCheck = (row: IUserName, col: Group) => async () => {\n cAdd(cKey(row.userId, col.id as string), check ?? []);\n const membership: GroupMembership = {\n type: 'groupmembership',\n } as GroupMembership;\n await memory.update((t) => [\n ...AddRecord(t, membership, user, memory),\n ...ReplaceRelatedRecord(\n t,\n membership as InitializedRecord,\n 'user',\n 'user',\n row.userId\n ),\n ...ReplaceRelatedRecord(\n t,\n membership as InitializedRecord,\n 'group',\n 'group',\n col.id\n ),\n ...ReplaceRelatedRecord(\n t,\n membership as InitializedRecord,\n 'role',\n 'role',\n getRoleId(RoleNames.Member)\n ),\n ]);\n };\n\n const handleUncheck = (row: IUserName, col: Group) => async () => {\n cDelete(cKey(row.userId, col.id as string), check ?? []);\n const recs = memberships.filter(\n (m) => related(m, 'user') === row.userId && related(m, 'group') === col.id\n );\n if (recs.length > 0)\n await memory.update((t) =>\n t.removeRecord({ type: 'groupmembership', id: recs[0].id as string })\n );\n };\n\n const canEditPeer = useMemo(\n () => getMyOrgRole(organization) === RoleNames.Admin && !offline,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [organization, offline]\n );\n\n const inUse = useMemo(\n () => peerGroups.map((c) => c.attributes.name.toLocaleLowerCase()).sort(),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [peerGroups]\n );\n\n return (\n \n \n \n \n {t.member}\n {peerGroups\n .sort((i, j) => (i.attributes.name <= j.attributes.name ? -1 : 1))\n .map((col) => (\n \n
\n \n \n \n
\n
\n ))}\n \n \n \n
\n
\n \n {userNames\n .sort((i, j) => (i.name <= j.name ? -1 : 1))\n .map((row) => (\n \n \n {row.name}\n \n {peerGroups\n .sort((i, j) =>\n i.attributes.name <= j.attributes.name ? -1 : 1\n )\n .map((col) => (\n \n {check?.includes(cKey(row.userId, col.id)) ? (\n \n \n \n ) : (\n \n \n \n )}\n \n ))}\n \n ))}\n \n
\n
\n );\n}\n\nexport default Peer;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Peers\\usePeerGroups.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":87,"column":5,"severity":1,"nodeType":null,"fix":{"range":[2550,2605],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'allUsersGroup'. Either include it or remove the dependency array.","line":46,"column":5,"nodeType":"ArrayExpression","endLine":46,"endColumn":10,"suggestions":[{"desc":"Update the dependencies array to be: [allUsersGroup, org]","fix":{"range":[1587,1592],"text":"[allUsersGroup, org]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'allUserId', 'getUserRec', 'groups', and 'user'. Either include them or remove the dependency array.","line":76,"column":6,"nodeType":"ArrayExpression","endLine":76,"endColumn":31,"suggestions":[{"desc":"Update the dependencies array to be: [allUserId, getUserRec, groups, memberships, org, user, users]","fix":{"range":[2325,2350],"text":"[allUserId, getUserRec, groups, memberships, org, user, users]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'memberships'. Either include it or remove the dependency array.","line":101,"column":6,"nodeType":"ArrayExpression","endLine":101,"endColumn":29,"suggestions":[{"desc":"Update the dependencies array to be: [userNames, peerGroups, memberships]","fix":{"range":[3068,3091],"text":"[userNames, peerGroups, memberships]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { useState, useEffect, useMemo } from 'react';\nimport { useGlobal } from '../../context/useGlobal';\nimport { User, GroupD, GroupMembership } from '../../model';\nimport { PermissionName, related, useAllUserGroup, useUser } from '../../crud';\nimport { useOrbitData } from '../../hoc/useOrbitData';\n\nexport interface IUserName {\n userId: string;\n name: string;\n}\n\nexport const usePeerGroups = (team?: string) => {\n const users = useOrbitData('user');\n const groups = useOrbitData('group');\n const memberships = useOrbitData('groupmembership');\n const [organization] = useGlobal('organization');\n const [org] = useState(team ?? organization);\n const allUsersGroup = useAllUserGroup();\n const { getUserRec } = useUser();\n const [userNames, setUserNames] = useState([]);\n const [peerGroups, setPeerGroups] = useState([]);\n const [myGroups, setMyGroups] = useState([]);\n const [check, setCheck] = useState();\n const [user] = useGlobal('user');\n const [offlineOnly] = useGlobal('offlineOnly'); //will be constant here\n\n const cKey = (userId: string, groupId: string) => `${userId}_${groupId}`;\n\n const cAdd = (v: string, c: string[]) => {\n if (!c.includes(v)) {\n c.push(v);\n setCheck(c.sort());\n }\n };\n\n const cDelete = (v: string, c: string[]) => {\n if (c.includes(v)) {\n c.splice(c.indexOf(v), 1);\n setCheck(c.sort());\n }\n };\n\n const allUserId = useMemo(\n () => allUsersGroup(org)?.id,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [org]\n );\n\n useEffect(() => {\n const memberIds = memberships\n .filter((m) => related(m, 'group') === allUserId)\n .map((m) => related(m, 'user'));\n\n setUserNames(\n memberIds.map((id) => {\n const userRec = getUserRec(id) as User;\n return { userId: id, name: userRec?.attributes?.name };\n })\n );\n\n const groupIds = memberships\n .filter((m) => related(m, 'user') === user)\n .map((om) => related(om, 'group'));\n\n setMyGroups(\n groups.filter(\n (g) =>\n g?.attributes &&\n !g.attributes?.allUsers &&\n groupIds.includes(g.id) &&\n related(g, 'owner') === org\n )\n );\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [memberships, org, users]);\n\n useEffect(() => {\n setPeerGroups(\n groups.filter(\n (g) =>\n g?.attributes &&\n !g.attributes?.allUsers &&\n related(g, 'owner') === org\n )\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [groups, org]);\n\n useEffect(() => {\n const users = userNames.map((r) => r.userId);\n const grps = peerGroups.map((c) => c.id);\n const checks = new Set();\n memberships.forEach((m) => {\n const u = related(m, 'user');\n const g = related(m, 'group');\n if (users.includes(u) && grps.includes(g)) checks.add(cKey(u, g));\n });\n setCheck(Array.from(checks));\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [userNames, peerGroups]);\n\n const getGroupId = function (name: string): string {\n const findit = groups.filter(\n (r) =>\n r.attributes &&\n r.attributes.name === name &&\n offlineOnly === Boolean(r?.keys?.remoteId)\n );\n if (findit.length > 0) return findit[0].id;\n return '';\n };\n\n const citGroup = useMemo(\n () =>\n peerGroups.filter((g) =>\n g.attributes.permissions?.includes(PermissionName.CIT)\n ).length > 0\n ? peerGroups.filter((g) =>\n g.attributes.permissions?.includes(PermissionName.CIT)\n )[0]\n : undefined,\n [peerGroups]\n );\n const mentorGroup = useMemo(\n () =>\n peerGroups.filter((g) =>\n g.attributes.permissions?.includes(PermissionName.Mentor)\n ).length > 0\n ? peerGroups.filter((g) =>\n g.attributes.permissions?.includes(PermissionName.Mentor)\n )[0]\n : undefined,\n [peerGroups]\n );\n return {\n userNames,\n peerGroups,\n check,\n cAdd,\n cDelete,\n cKey,\n myGroups,\n getGroupId,\n citGroup,\n mentorGroup,\n };\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PlanTabs.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setTab', 'tab', and 'tabNm'. Either include them or remove the dependency array.","line":99,"column":6,"nodeType":"ArrayExpression","endLine":99,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [setTab, tab, tabNm]","fix":{"range":[3199,3201],"text":"[setTab, tab, tabNm]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PlanTabsEnum.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PlayButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PolicyDialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ProfileDialog.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":3,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":3,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ProfileDialog.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'no-template-curly-in-string').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,48],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearCompleted', 'clearRequested', 'handleSave', 'isChanged', 'myChanged', and 'saveRequested'. Either include them or remove the dependency array.","line":433,"column":6,"nodeType":"ArrayExpression","endLine":433,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [clearCompleted, clearRequested, handleSave, isChanged, myChanged, saveRequested, toolsChanged]","fix":{"range":[12917,12931],"text":"[clearCompleted, clearRequested, handleSave, isChanged, myChanged, saveRequested, toolsChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'avatarUrl', 'bcp47', 'email', 'family', 'given', 'hotKeys', 'isDeveloper', 'locale', 'memory?.cache', 'name', 'organization', 'phone', 'progBar', 'speed', 'timerDir', 'timezone', and 'users'. Either include them or remove the dependency array.","line":737,"column":6,"nodeType":"ArrayExpression","endLine":737,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [user, editId, name, given, family, email, phone, timezone, locale, bcp47, timerDir, speed, progBar, hotKeys, avatarUrl, isDeveloper, users, memory?.cache, organization]","fix":{"range":[22024,22038],"text":"[user, editId, name, given, family, email, phone, timezone, locale, bcp47, timerDir, speed, progBar, hotKeys, avatarUrl, isDeveloper, users, memory?.cache, organization]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'toolChanged'. Either include it or remove the dependency array.","line":751,"column":6,"nodeType":"ArrayExpression","endLine":751,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [timezone, toolChanged]","fix":{"range":[22405,22415],"text":"[timezone, toolChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable no-template-curly-in-string */\nimport React, { useState, useContext, useRef, useEffect } from 'react';\nimport {\n IMainStrings,\n IProfileStrings,\n UserD,\n DigestPreference,\n OrganizationMembershipD,\n User,\n OrganizationMembership,\n} from '../model';\nimport {\n Dialog,\n DialogContent,\n FormControlLabel,\n Avatar,\n SxProps,\n Box,\n Grid,\n GridProps,\n FormControl,\n FormGroup,\n TextField,\n MenuItem,\n Checkbox,\n Switch,\n Stack,\n} from '@mui/material';\nimport Confirm from '../components/AlertDialog';\nimport Typography, { TypographyProps } from '@mui/material/Typography';\nimport { styled } from '@mui/material/styles';\nimport { AlertSeverity, useSnackBar } from '../hoc/SnackBar';\nimport { langName, UiLoc } from '../utils/langName';\nimport { localeDefault } from '../utils/localeDefault';\nimport { LocalKey, localUserKey } from '../utils/localUserKey';\nimport { makeAbbr } from '../utils/makeAbbr';\nimport { uiLang, uiLangDev } from '../utils/uiLang';\nimport { useMyNavigate } from '../utils/useMyNavigate';\nimport { useWaitForRemoteQueue } from '../utils/useWaitForRemoteQueue';\nimport { waitForIt } from '../utils/waitForIt';\nimport { mainSelector } from '../selector';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport ParatextLinkedButton from '../components/ParatextLinkedButton';\nimport { profileSelector } from '../selector';\nimport { UnsavedContext } from '../context/UnsavedContext';\nimport { useOrbitData } from '../hoc/useOrbitData';\nimport { RecordTransformResult, InitializedRecord } from '@orbit/records';\nimport { useDispatch } from 'react-redux';\nimport { useGlobal } from '../context/useGlobal';\nimport { setLanguage as setLanguageAction } from '../store/localization/actions';\nimport { related } from '../crud/related';\nimport { RemoveUserFromOrg } from '../crud/user';\nimport { useAddToOrgAndGroup } from '../crud/useAddToOrgAndGroup';\nimport { useRole } from '../crud/useRole';\nimport { useTeamDelete } from '../crud/useTeamDelete';\nimport { useUser } from '../crud/useUser';\nimport { DateTime } from 'luxon';\nimport {\n AddRecord,\n UpdateRecord,\n UpdateRelatedRecord,\n} from '../model/baseModel';\nimport SelectRole from '../control/SelectRole';\nimport ExtendableDeleteExpansion from './ExtendableDeleteExpansion';\nimport { AltActionBar } from './AltActionBar';\nimport { StyledDialogTitle } from './StyledDialogTitle';\nimport { Button } from '../control/Button';\n\nconst Caption = styled(Typography)(() => ({\n width: 150,\n textAlign: 'left',\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n}));\n\nconst textFieldProps = {\n mx: 1,\n width: '100%',\n '&:has([readOnly]) ': {\n height: '47px',\n marginBottom: '1px',\n '& .MuiInputLabel-root': {\n color: 'rgba(0, 0, 0, 0.6)',\n },\n },\n} as SxProps;\n\nconst selectProps = {\n mx: 1,\n width: '100%',\n '&:has([readOnly]) ': {\n height: '47px',\n marginBottom: '1px',\n '& .MuiInputLabel-root': {\n color: 'rgba(0, 0, 0, 0.6)',\n },\n },\n} as SxProps;\n\nconst menuProps = {\n width: '100px',\n '&:has([readOnly]) ': {\n '& .MuiSvgIcon-root-MuiSelect-icon': {\n display: 'none',\n },\n '& .MuiInputLabel-root': {\n color: 'rgba(0, 0, 0, 0.6)',\n },\n },\n} as SxProps;\n\nconst bigAvatarProps = {\n width: '150px',\n height: '150px',\n} as SxProps;\n\nconst profileContentProps = {\n display: 'flex',\n flexDirection: 'row',\n flexWrap: 'wrap',\n padding: '0px',\n margin: '0px',\n} as SxProps;\n\nconst profilePanelProps = {\n display: 'flex',\n flex: '1 1 40%',\n flexDirection: 'column',\n justifyContent: 'center',\n maxWidth: '100%',\n backgroundColor: 'secondary.dark',\n textAlign: 'center',\n position: 'relative',\n} as SxProps;\n\nconst profileMainProps = {\n display: 'flex',\n flex: '1 1 calc(60% - 40px)',\n flexDirection: 'column',\n maxWidth: '100%',\n justifyContent: 'center',\n mx: '10px',\n padding: '10px',\n paddingBottom: '0px',\n} as SxProps;\n\nconst profileEmailProps = {\n width: '100%',\n overflow: 'visible',\n position: 'relative',\n textAlign: 'center',\n color: 'primary.contrastText',\n marginTop: '10px',\n marginBottom: '10px',\n} as SxProps;\n\nconst deleteUserProps = {\n color: 'primary.dark',\n backgroundColor: 'primary.contrastText',\n opacity: '100%',\n '&.Mui-disabled': {\n color: 'primary.dark',\n backgroundColor: 'primary.contrastText',\n opacity: '50%',\n },\n '&:hover': {\n borderColor: 'primary.contrastText',\n backgroundColor: 'primary.contrastText',\n boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.2)',\n opacity: '90%',\n },\n} as SxProps;\n\nconst frequencyProps = {\n marginLeft: '5px',\n padding: '0px',\n width: '100%',\n '& .MuiInputBase-root': {\n backgroundColor: 'primary.dark', // Background color of the input\n },\n '& .MuiOutlinedInput-root': {\n '& fieldset': {\n borderColor: 'primary.contrastText', // Border color of the input\n },\n '&:hover fieldset': {\n borderColor: 'primary.contrastText', // Border color on hover\n },\n '&.Mui-focused fieldset': {\n borderColor: 'secondary.dark', // Border color when focused\n },\n '&.Mui-disabled': {\n opacity: '75%', // Border opacity when disabled\n },\n '&.Mui-disabled:hover fieldset': {\n borderColor: 'rgba(0, 0, 0, .38)', // Border color remains unchanged on hover when disabled\n },\n },\n '& .MuiInputBase-input': {\n color: 'primary.contrastText', // Text color of the input\n },\n '& .MuiInputAdornment-root': {\n color: 'primary.contrastText',\n },\n} as SxProps;\n\nconst toggleSwitchProps = {\n margin: '0px',\n '& .MuiSwitch-switchBase': {\n color: 'primary.contrastText', // Color of the thumb when the switch is unchecked\n '&.Mui-checked': {\n color: 'primary.contrastText', // Color of the thumb when the switch is checked\n '& + .MuiSwitch-track': {\n backgroundColor: 'primary.contrastText', // Color of the track when the switch is checked\n opacity: '20%',\n },\n },\n },\n '& .MuiSwitch-track': {\n backgroundColor: 'secondary.contrastText', // Color of the track when the switch is unchecked\n opacity: '20%',\n },\n} as SxProps;\n\ninterface IBigAvatarProps {\n avatarUrl: string | null;\n name: string;\n}\nconst BigAvatar = (props: IBigAvatarProps) => {\n const { avatarUrl, name } = props;\n\n if (!avatarUrl || avatarUrl === '') {\n return {makeAbbr(name)};\n }\n return ;\n};\n\nconst StyledGrid = styled(Grid)(() => ({\n padding: '0 30px',\n}));\n\nexport interface ProfileDialogProps {\n mode: 'create' | 'editMember' | 'viewMyAccount';\n open: boolean;\n editId?: string;\n onClose?: () => void;\n onSave?: () => void;\n onSaveCompleted?: () => void;\n onCancel?: () => void;\n finishAdd?: () => void;\n}\nexport function ProfileDialog(props: ProfileDialogProps) {\n const {\n mode,\n open,\n editId,\n onClose,\n onSave,\n onSaveCompleted,\n onCancel,\n finishAdd,\n } = props;\n const users = useOrbitData('user');\n const t: IMainStrings = useSelector(mainSelector, shallowEqual);\n const tp: IProfileStrings = useSelector(profileSelector, shallowEqual);\n const dispatch = useDispatch();\n const setLanguage = (lang: string) =>\n dispatch(setLanguageAction(lang) as any);\n const [isOffline] = useGlobal('offline'); //verified this is not used in a function 2/18/25\n const [memory] = useGlobal('memory');\n const [organization] = useGlobal('organization');\n const [user, setUser] = useGlobal('user');\n const [offlineOnly] = useGlobal('offlineOnly'); //will be constant here\n const [isDeveloper] = useGlobal('developer');\n const navigate = useMyNavigate();\n const { getUserRec } = useUser();\n const { getMbrRoleRec, userIsAdmin, userIsSharedContentAdmin } = useRole();\n const [uiLanguages] = useState(isDeveloper ? uiLangDev : uiLang);\n const [currentUser, setCurrentUser] = useState();\n const [name, setName] = useState('');\n const [given, setGiven] = useState(null);\n const [family, setFamily] = useState(null);\n const [email, setEmail] = useState('');\n const [timezone, setTimezone] = useState(\n DateTime.local().zoneName || ''\n );\n const [sync, setSync] = useState(true);\n const [syncFreq, setSyncFreq] = useState(2);\n const [role, setRole] = useState('');\n const [locale, setLocale] = useState(localeDefault(isDeveloper));\n const [news, setNews] = useState(null);\n const [sharedContent, setSharedContent] = useState(false);\n const [digest, setDigest] = useState(null);\n const [phone, setPhone] = useState(null);\n const [bcp47, setBcp47] = useState(null);\n const [timerDir, setTimerDir] = useState(null);\n const [speed, setSpeed] = useState(null);\n const [progBar, setProgBar] = useState(null);\n const [hotKeys, setHotKeys] = useState(null);\n const [avatarUrl, setAvatarUrl] = useState(null);\n const [showDetail, setShowDetail] = useState(false);\n const [locked, setLocked] = useState(false);\n const [deleteItem, setDeleteItem] = useState('');\n const [dupName, setDupName] = useState(false);\n const [view, setView] = useState('');\n const {\n startSave,\n saveCompleted,\n toolChanged,\n toolsChanged,\n saveRequested,\n clearRequested,\n clearCompleted,\n isChanged,\n } = useContext(UnsavedContext).state;\n const [myChanged, setMyChanged] = useState(false);\n const [readOnly, setReadOnly] = useState(true);\n const { showMessage } = useSnackBar();\n const addToOrgAndGroup = useAddToOrgAndGroup();\n const teamDelete = useTeamDelete();\n const toolId = 'profile';\n const saving = useRef(false);\n const [confirmCancel, setConfirmCancel] = useState();\n const [confirmClose, setConfirmClose] = useState();\n const waitForRemoteQueue = useWaitForRemoteQueue();\n\n const doClose = () => {\n const view = localStorage.getItem(localUserKey(LocalKey.url));\n if (view) {\n setView(view);\n }\n if (onClose) {\n onClose();\n }\n };\n\n const handleNameClick = (event: React.MouseEvent) => {\n if (event.shiftKey) setShowDetail(!showDetail);\n };\n\n const handleNameChange = (e: any) => {\n if (e.target.value === email) {\n showMessage(tp.nameNotEmail);\n return;\n }\n toolChanged(toolId, true);\n setName(e.target.value);\n if (!currentUser || (currentUser.attributes?.givenName || '') === '') {\n const parts = e.target.value.split(' ');\n setGiven(parts[0]);\n if (parts.length > 1) {\n setFamily(parts[parts.length - 1]);\n }\n }\n if (editId) {\n const userRecs = users.filter(\n (u) => u.attributes?.name === e.target.value\n );\n const newDupName = userRecs.length > 0;\n if (newDupName !== dupName) setDupName(newDupName);\n }\n };\n\n const handleGivenChange = (e: any) => {\n toolChanged(toolId, true);\n setGiven(e.target.value);\n };\n\n const handleFamilyChange = (e: any) => {\n toolChanged(toolId, true);\n setFamily(e.target.value);\n };\n const handleSyncFreqSwitch = (e: React.ChangeEvent) => {\n toolChanged(toolId, true);\n setSync(e.target.checked);\n const newFreq = e.target.checked ? 2 : 0;\n setSyncFreq(newFreq);\n const hk = JSON.parse(hotKeys ?? '{}');\n setHotKeys(JSON.stringify({ ...hk, syncFreq: newFreq }));\n };\n const handleSyncFreqChange = (e: any) => {\n if (e.target.value < 1) e.target.value = 1;\n if (e.target.value > 720) e.target.value = 720;\n toolChanged(toolId, true);\n setSyncFreq(e.target.value);\n const hk = JSON.parse(hotKeys ?? '{}');\n setHotKeys(JSON.stringify({ ...hk, syncFreq: e.target.value }));\n };\n const handlePhoneChange = (e: any) => {\n toolChanged(toolId, true);\n setPhone(e.target.value);\n };\n\n const handleTimezoneChange = (e: any) => {\n toolChanged(toolId, true);\n setTimezone(e.target.value);\n };\n\n const handleRoleChange = (e: string) => {\n toolChanged(toolId, true);\n setRole(e);\n };\n\n const handleLocaleChange = (e: any) => {\n toolChanged(toolId, true);\n setLocale(e.target.value);\n };\n\n const handleLockedChange = () => {\n toolChanged(toolId, true);\n setLocked(!locked);\n };\n\n const handleSharedContentChange = () => {\n toolChanged(toolId, true);\n setSharedContent(!sharedContent);\n };\n\n const handleDigestChange = () => {\n toolChanged(toolId, true);\n setDigest(\n digest ? DigestPreference.noDigest : DigestPreference.dailyDigest\n );\n };\n useEffect(() => {\n if (saveRequested(toolId)) {\n handleSave();\n } else if (clearRequested(toolId)) {\n clearCompleted(toolId);\n }\n const changed = isChanged(toolId);\n if (changed !== myChanged) setMyChanged(changed);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [toolsChanged]);\n\n const handleSave = () => {\n if (!saving.current && isChanged(toolId)) {\n startSave(toolId);\n saving.current = true;\n const currentUserId = currentUser === undefined ? user : currentUser.id; //currentuser will not be undefined here\n memory\n .update(\n (t) =>\n UpdateRecord(\n t,\n {\n type: 'user',\n id: currentUserId,\n attributes: {\n name,\n givenName: given,\n familyName: family,\n email,\n phone,\n timezone,\n locale,\n isLocked: locked,\n uilanguagebcp47: bcp47,\n timercountUp: timerDir,\n playbackSpeed: speed,\n progressbarTypeid: progBar,\n hotKeys: hotKeys,\n digestPreference: digest,\n newsPreference: news,\n sharedContentCreator: sharedContent,\n avatarUrl,\n },\n } as UserD,\n currentUser !== undefined ? currentUser.id : ''\n )\n // we aren't allowing them to change owner organization currently\n )\n .then((r) => {\n if (r) {\n // set the currentUser to the saved user data unless admin editing\n if (!editId) {\n const res = r as RecordTransformResult[];\n const user = res.at(0) as UserD;\n setCurrentUser(user);\n setUser(user.id);\n }\n if (onSaveCompleted) {\n onSaveCompleted();\n }\n }\n });\n const mbrRec = getMbrRoleRec(\n 'organization',\n organization,\n currentUserId\n ) as OrganizationMembershipD;\n if (mbrRec) {\n const curRoleId = related(mbrRec, 'role');\n if (curRoleId !== role) {\n memory.update((t) =>\n UpdateRelatedRecord(t, mbrRec, 'role', 'role', role, user)\n );\n }\n }\n if (!editId) setLanguage(locale);\n }\n saveCompleted(toolId);\n saving.current = false;\n if (onSave) {\n onSave();\n }\n setReadOnly(mode === 'viewMyAccount');\n };\n\n const handleAdd = async () => {\n if (isChanged(toolId)) {\n const userRec = {\n type: 'user',\n attributes: {\n name,\n givenName: given,\n familyName: family,\n email,\n phone,\n timezone,\n locale,\n isLocked: locked,\n uilanguagebcp47: bcp47,\n timercountUp: timerDir,\n playbackSpeed: speed,\n progressbarTypeid: progBar,\n digestPreference: digest,\n newsPreference: news,\n sharedContentCreator: sharedContent,\n hotKeys,\n avatarUrl,\n },\n } as User;\n if (!editId || !organization) {\n await memory.update((t) => AddRecord(t, userRec, user, memory));\n if (offlineOnly) setUser(userRec.id as string);\n } else {\n addToOrgAndGroup(userRec, true);\n }\n if (offlineOnly) {\n await waitForIt(\n 'record added',\n () => Boolean(userRec.id),\n () => false,\n 100\n );\n if (offlineOnly)\n localStorage.setItem(LocalKey.userId, userRec.id as string);\n }\n saveCompleted(toolId);\n }\n if (finishAdd) {\n finishAdd();\n }\n };\n\n const resetUserData = () => {\n const attr = currentUser?.attributes;\n if (!attr) return;\n setName(attr.name !== attr.email ? attr.name : '');\n setGiven(attr.givenName ? attr.givenName : '');\n setFamily(attr.familyName ? attr.familyName : '');\n setEmail(attr.email.toLowerCase());\n setPhone(attr.phone);\n setTimezone(attr.timezone || '');\n setLocale(attr.locale ? attr.locale : localeDefault(isDeveloper));\n setNews(attr.newsPreference);\n setSharedContent(attr.sharedContentCreator ?? false);\n setDigest(attr.digestPreference);\n setLocked(true);\n setBcp47(attr.uilanguagebcp47);\n setTimerDir(attr.timercountUp);\n setSpeed(attr.playbackSpeed);\n setProgBar(attr.progressbarTypeid);\n setHotKeys(attr.hotKeys);\n setAvatarUrl(attr.avatarUrl);\n const syncFreq = getSyncFreq(attr.hotKeys);\n setSyncFreq(syncFreq);\n setSync(syncFreq > 0);\n };\n\n const handleCancel = () => {\n if (myChanged) {\n const defLocale =\n currentUser?.attributes?.locale === '' ? tp.defaultLocale : '';\n const defTimezone =\n currentUser?.attributes?.timezone === '' ? tp.defaultTimezone : '';\n let message = tp.discardChanges;\n const message2 = tp.discardChangesExplained;\n if (defLocale && defTimezone) {\n message = message2.replace('{0}', `${defLocale} ${defTimezone}`);\n } else if (defLocale) {\n message = message2.replace('{0}', defLocale);\n } else if (defTimezone) {\n message = message2.replace('{0}', defTimezone);\n }\n setConfirmCancel(message);\n } else handleCancelConfirmed();\n };\n\n const handleCancelConfirmed = () => {\n setConfirmCancel(undefined);\n toolChanged(toolId, false);\n if (editId) {\n const userId = localStorage.getItem(LocalKey.userId);\n if (!userId && offlineOnly) {\n setView('Logout');\n return;\n }\n }\n resetUserData();\n if (onCancel) {\n onCancel();\n }\n setReadOnly(mode === 'viewMyAccount');\n };\n\n const handleCancelAborted = () => {\n setConfirmCancel(undefined);\n };\n\n const handleCloseConfirmed = () => {\n setConfirmClose(undefined);\n toolChanged(toolId, false);\n if (editId) {\n const userId = localStorage.getItem(LocalKey.userId);\n if (!userId && offlineOnly) {\n setView('Logout');\n return;\n }\n }\n resetUserData();\n doClose();\n setReadOnly(mode === 'viewMyAccount');\n };\n\n const handleCloseAborted = () => {\n setConfirmClose(undefined);\n };\n\n const handleDelete = () => {\n if (currentUser) setDeleteItem(currentUser.id);\n };\n const handleDeleteConfirmed = async () => {\n const deleteRec = getUserRec(deleteItem);\n try {\n await waitForRemoteQueue('wait for any changes to finish');\n await RemoveUserFromOrg(memory, deleteRec, undefined, user, teamDelete);\n await memory.update((tb) =>\n tb.removeRecord({ type: 'user', id: deleteItem })\n );\n //wait to be sure orbit remote is done also\n try {\n await waitForRemoteQueue('logout after user delete');\n } catch {\n //well we tried...\n }\n localStorage.removeItem(LocalKey.userId);\n setView('Logout');\n } catch {\n showMessage(tp.deleteFailed, AlertSeverity.Error);\n setDeleteItem('');\n }\n };\n\n const handleDeleteRefused = () => {\n setDeleteItem('');\n };\n\n useEffect(() => {\n let userRec = {\n type: 'user',\n id: '',\n attributes: {\n name,\n givenName: given,\n familyName: family,\n email,\n phone,\n timezone,\n locale,\n isLocked: true,\n auth0Id: '',\n silUserid: 0,\n identityToken: '',\n uilanguagebcp47: bcp47,\n timercountUp: timerDir,\n playbackSpeed: speed,\n progressbarTypeid: progBar,\n digestPreference: DigestPreference.dailyDigest,\n newsPreference: false,\n sharedContentCreator: false,\n hotKeys,\n avatarUrl,\n },\n } as User;\n if (!editId || !/Add/i.test(editId)) {\n const current = users.filter((u) => u.id === (editId ? editId : user));\n if (current.length === 1) {\n userRec = current[0];\n setCurrentUser(userRec as UserD);\n const orgMbrRecs = memory?.cache.query((q) =>\n q.findRecords('organizationmembership')\n ) as OrganizationMembership[];\n const mbrRec = orgMbrRecs.filter(\n (r) =>\n related(r, 'user') === userRec.id &&\n related(r, 'organization') === organization\n );\n if (mbrRec.length > 0) {\n setRole(related(mbrRec[0], 'role'));\n }\n }\n }\n const attr = userRec.attributes;\n if (!attr) return;\n setName(attr.name !== attr.email ? attr.name : '');\n setGiven(attr.givenName ? attr.givenName : '');\n setFamily(attr.familyName ? attr.familyName : '');\n setEmail(attr.email.toLowerCase());\n setPhone(attr.phone);\n setTimezone(attr.timezone || '');\n setLocale(attr.locale ? attr.locale : localeDefault(isDeveloper));\n setNews(attr.newsPreference);\n setSharedContent(attr.sharedContentCreator ?? false);\n setDigest(attr.digestPreference);\n setLocked(true);\n setBcp47(attr.uilanguagebcp47);\n setTimerDir(attr.timercountUp);\n setSpeed(attr.playbackSpeed);\n setProgBar(attr.progressbarTypeid);\n setHotKeys(attr.hotKeys);\n setAvatarUrl(attr.avatarUrl);\n const syncFreq = getSyncFreq(attr.hotKeys);\n setSyncFreq(syncFreq);\n setSync(syncFreq > 0);\n /* eslint-disable-next-line react-hooks/exhaustive-deps */\n }, [user, editId]);\n\n const getSyncFreq = (hotKeys: string | null) => {\n const hk = JSON.parse(hotKeys ?? '{}');\n return hk.syncFreq ?? 2;\n };\n\n useEffect(() => {\n if (timezone === '') {\n const myZone = DateTime.local().zoneName;\n setTimezone(myZone || '');\n toolChanged(toolId, true);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [timezone]);\n\n const userNotComplete = () =>\n currentUser === undefined ||\n currentUser.attributes?.name.toLowerCase() ===\n currentUser.attributes?.email.toLowerCase();\n\n const requiredComplete = () =>\n (name || '') !== '' &&\n (family || '') !== '' &&\n (given || '') !== '' &&\n (timezone || '') !== '' &&\n (locale || '') !== '';\n\n if (/Logout/i.test(view)) navigate('/logout');\n else if (/access/i.test(view)) navigate('/');\n const handleClose = () => {\n if (onClose) {\n if (myChanged) {\n setConfirmClose(tp.discardChanges);\n } else handleCloseConfirmed();\n }\n };\n\n useEffect(() => setReadOnly(mode === 'viewMyAccount'), [mode]);\n\n useEffect(() => {\n if (mode !== 'editMember' || !editId || /Add/i.test(editId)) return;\n if (isOffline && !offlineOnly) setReadOnly(true);\n else setReadOnly(false);\n }, [mode, editId, isOffline, offlineOnly, open]);\n\n const memberEditOfflineBlocked =\n mode === 'editMember' &&\n !!editId &&\n !/Add/i.test(editId) &&\n isOffline &&\n !offlineOnly;\n\n const onEditClicked = () => {\n if (memberEditOfflineBlocked) return;\n setReadOnly(false);\n };\n\n return (\n \n {\n if (myChanged) {\n setConfirmClose(tp.discardChanges);\n } else handleCloseConfirmed();\n }\n : undefined\n }\n >\n {editId && /Add/i.test(editId)\n ? tp.addMember\n : userNotComplete()\n ? tp.completeProfile\n : editId\n ? tp.editMember\n : t.myAccount}\n \n \n \n \n \n \n \n {email || ''}\n {((editId && /Add/i.test(editId)) || !userNotComplete()) && (\n \n {tp.edit}\n \n )}\n \n \n {!readOnly &&\n (!isOffline || offlineOnly) &&\n !editId &&\n currentUser &&\n currentUser.attributes?.name !== currentUser.attributes?.email && (\n \n \n {tp.additionalSettings}\n \n \n 0}\n onChange={handleSyncFreqSwitch}\n />\n }\n labelPlacement=\"start\"\n label={tp.syncFrequencyEnable}\n sx={toggleSwitchProps}\n />\n \n }\n labelPlacement=\"start\"\n label={tp.syncFrequencyLabel}\n sx={{ marginLeft: '2em' }}\n disabled={!sync}\n />\n \n \n )}\n \n \n {readOnly ? (\n \n \n \n \n \n \n {showDetail && (\n \n )}\n \n ) : (\n \n \n \n \n {tp.userExists}\n \n )\n }\n required\n autoFocus\n />\n }\n label=\"\"\n />\n \n }\n label=\"\"\n />\n \n }\n label=\"\"\n />\n {userIsAdmin && editId && email !== '' && (\n \n }\n label=\"\"\n />\n )}\n \n {uiLanguages.map((option: string, idx: number) => (\n \n {langName(locale as UiLoc, option as UiLoc)}\n \n ))}\n \n }\n label=\"\"\n />\n \n {Intl.supportedValuesOf('timeZone').map(\n (option: string, idx: number) => (\n \n {option}\n \n )\n )}\n \n }\n label=\"\"\n />\n {email !== '' && (\n \n }\n label={tp.sendDigest}\n />\n )}\n {userIsSharedContentAdmin && (\n \n }\n label={tp.sharedContentCreator}\n />\n )}\n {showDetail && (\n <>\n \n }\n label=\"\"\n />\n {userIsAdmin && (\n \n }\n label={tp.locked}\n />\n )}\n \n )}\n \n \n \n )}\n {!readOnly && (\n \n \n \n )}\n \n {!readOnly && deleteItem !== '' && (\n \n )}\n {!readOnly && confirmCancel && (\n \n )}\n {!readOnly && confirmClose && (\n \n )}\n \n \n );\n}\nexport default ProfileDialog;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ProjectDownload.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'backup', 'doProjectExport', 'finish', 'getGlobal', 'memory', 'offlineUpdates', 'projectIds', and 'setBusy'. Either include them or remove the dependency array.","line":138,"column":6,"nodeType":"ArrayExpression","endLine":138,"endColumn":54,"suggestions":[{"desc":"Update the dependencies array to be: [open, progress, currentStep, projectIds.length, projectIds, backup, memory, offlineUpdates, getGlobal, doProjectExport, setBusy, finish]","fix":{"range":[4547,4595],"text":"[open, progress, currentStep, projectIds.length, projectIds, backup, memory, offlineUpdates, getGlobal, doProjectExport, setBusy, finish]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'enableOffsite', 'exportComplete', 'open', 'setEngableOffsite', 'showMessage', 'showTitledMessage', 't.error', and 'translateError'. Either include them or remove the dependency array.","line":162,"column":6,"nodeType":"ArrayExpression","endLine":162,"endColumn":32,"suggestions":[{"desc":"Update the dependencies array to be: [enableOffsite, exportComplete, exportFile, exportStatus, open, setEngableOffsite, showMessage, showTitledMessage, t.error, translateError]","fix":{"range":[5314,5340],"text":"[enableOffsite, exportComplete, exportFile, exportStatus, open, setEngableOffsite, showMessage, showTitledMessage, t.error, translateError]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'errorReporter', 'exportName', 'exportUrl', 'showTitledMessage', 't.downloadProject', and 't.downloading'. Either include them or remove the dependency array.","line":220,"column":6,"nodeType":"ArrayExpression","endLine":220,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [errorReporter, exportName, exportUrl, progress, showTitledMessage, t.downloadProject, t.downloading]","fix":{"range":[7313,7323],"text":"[errorReporter, exportName, exportUrl, progress, showTitledMessage, t.downloadProject, t.downloading]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'currentStep', 'exportName', 'memory', 'offlineUpdates', and 'projectIds'. Either include them or remove the dependency array. You can also do a functional update 'setCurrentStep(c => ...)' if you only need 'currentStep' in the 'setCurrentStep' call.","line":242,"column":6,"nodeType":"ArrayExpression","endLine":242,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [currentStep, exportName, memory, offlineUpdates, progress, projectIds]","fix":{"range":[8020,8030],"text":"[currentStep, exportName, memory, offlineUpdates, progress, projectIds]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'exportComplete', 'finish', 'projectIds.length', and 'setBusy'. Either include them or remove the dependency array.","line":253,"column":6,"nodeType":"ArrayExpression","endLine":253,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [exportComplete, finish, projectIds.length, setBusy]","fix":{"range":[8262,8264],"text":"[exportComplete, finish, projectIds.length, setBusy]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ProjectDownloadAlert.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'cb', 'getNeedyRemoteIds', 'handleClose', and 'tokenCtx?.state?.accessToken'. Either include them or remove the dependency array.","line":360,"column":6,"nodeType":"ArrayExpression","endLine":360,"endColumn":45,"suggestions":[{"desc":"Update the dependencies array to be: [offlineProjects, projects, mediafiles, tokenCtx?.state?.accessToken, cb, getNeedyRemoteIds, handleClose]","fix":{"range":[12241,12280],"text":"[offlineProjects, projects, mediafiles, tokenCtx?.state?.accessToken, cb, getNeedyRemoteIds, handleClose]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ProvideRights.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":122,"column":5,"nodeType":"ArrayExpression","endLine":122,"endColumn":27,"suggestions":[{"desc":"Update the dependencies array to be: [memory, organizationId, team]","fix":{"range":[3898,3920],"text":"[memory, organizationId, team]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'toolChanged'. Either include it or remove the dependency array.","line":128,"column":6,"nodeType":"ArrayExpression","endLine":128,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [canSave, toolChanged]","fix":{"range":[4046,4055],"text":"[canSave, toolChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getOrgDefault'. Either include it or remove the dependency array.","line":172,"column":6,"nodeType":"ArrayExpression","endLine":172,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, speaker]","fix":{"range":[5240,5249],"text":"[getOrgDefault, speaker]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'updatePaperWidth'. Either include it or remove the dependency array. Mutable values like 'paperRef.current' aren't valid dependencies because mutating them doesn't re-render the component.","line":183,"column":6,"nodeType":"ArrayExpression","endLine":183,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [updatePaperWidth]","fix":{"range":[5592,5610],"text":"[updatePaperWidth]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearCompleted', 'clearRequested', 'handleSave', and 'saveRequested'. Either include them or remove the dependency array.","line":198,"column":6,"nodeType":"ArrayExpression","endLine":198,"endColumn":29,"suggestions":[{"desc":"Update the dependencies array to be: [toolsChanged, canSave, saveRequested, handleSave, clearRequested, clearCompleted]","fix":{"range":[5934,5957],"text":"[toolsChanged, canSave, saveRequested, handleSave, clearRequested, clearCompleted]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PublishExpansion.test.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,61],"text":" "}},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'screen' is defined but never used. Allowed unused vars must match /^_/u.","line":7,"column":3,"nodeType":null,"messageId":"unusedVar","endLine":7,"endColumn":9}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":1,"source":"// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport React from 'react';\nimport {\n act,\n fireEvent,\n render,\n screen,\n waitFor,\n} from '@testing-library/react';\nimport { Bible, ICardsStrings, Organization, ProjectD } from '../model';\n\nconst mockShowMessage = jest.fn();\nconst mockGetBibleMediaPlan = jest.fn();\nlet mockProjects: ProjectD[] = [];\nlet capturedCanRecord: (() => Promise) | undefined;\n\njest.mock('../control/MediaTitle', () => ({\n __esModule: true,\n default: (props: { canRecord?: () => Promise }) => {\n capturedCanRecord = props.canRecord;\n return
;\n },\n}));\n\njest.mock('../control', () => ({\n LightTooltip: ({ children }: { children: React.ReactNode }) => (\n <>{children}\n ),\n}));\n\njest.mock('../hoc/SnackBar', () => ({\n useSnackBar: () => ({ showMessage: mockShowMessage }),\n}));\n\njest.mock('../hoc/useOrbitData', () => ({\n useOrbitData: () => mockProjects,\n}));\n\njest.mock('../crud/useBibleMedia', () => ({\n useBibleMedia: () => ({ getBibleMediaPlan: mockGetBibleMediaPlan }),\n}));\n\njest.mock('../utils', () => ({\n isLangSet: (code?: string) => Boolean(code),\n}));\n\njest.mock('../crud', () => ({\n related: (\n rec: { relationships?: Record },\n key: string\n ) => rec?.relationships?.[key]?.data?.id,\n useOrgDefaults: () => ({ getDefault: () => undefined }),\n useBible: () => ({ getPublishingData: () => undefined }),\n orgDefaultLangProps: 'langProps',\n pubDataCopyright: 'copyright',\n pubDataLangProps: 'langProps',\n}));\n\nimport PublishExpansion from './PublishExpansion';\n\nconst t = {\n publishing: 'Publishing',\n bibleid: 'Bible Id',\n bibleIdExplain: 'Explain',\n language: 'Language: {0}',\n biblename: 'Bible Name',\n description: 'Description',\n copyright: 'Copyright',\n projectRequired: 'A project must be added before recordings are allowed',\n planNotFound: 'Plan not found. Please contact APM Support.',\n bibleidformat: 'Bible Id must start with a 3-letter language code',\n bibleidiso: 'Bible Id must match the language',\n bibleidexists: 'This Bible Id already exists',\n bibleOwnerRights: \"Team '{0}' is the owner of this Bible.\",\n} as ICardsStrings;\n\nconst team = { id: 'team-1' } as Organization;\n\nconst teamProject = {\n id: 'proj-1',\n type: 'project',\n relationships: {\n organization: { data: { type: 'organization', id: 'team-1' } },\n },\n} as ProjectD;\n\ndescribe('PublishExpansion BibleMedia plan', () => {\n beforeEach(() => {\n mockShowMessage.mockReset();\n mockGetBibleMediaPlan.mockReset();\n mockProjects = [];\n capturedCanRecord = undefined;\n });\n\n const renderPublish = () =>\n render(\n \n );\n\n it('shows a support snackbar when the BibleMedia plan is missing', async () => {\n mockGetBibleMediaPlan.mockResolvedValue(undefined);\n renderPublish();\n await waitFor(() => expect(capturedCanRecord).toBeDefined());\n\n let allowed = true;\n await act(async () => {\n allowed = await capturedCanRecord!();\n });\n\n expect(allowed).toBe(false);\n expect(mockShowMessage).toHaveBeenCalledWith(t.planNotFound);\n });\n\n it('does not show the plan snackbar when a BibleMedia plan exists', async () => {\n mockGetBibleMediaPlan.mockResolvedValue({ id: 'plan-1' });\n mockProjects = [teamProject];\n renderPublish();\n await waitFor(() => expect(capturedCanRecord).toBeDefined());\n\n let allowed = false;\n await act(async () => {\n allowed = await capturedCanRecord!();\n });\n\n expect(allowed).toBe(true);\n expect(mockShowMessage).not.toHaveBeenCalledWith(t.planNotFound);\n });\n});\n\ndescribe('PublishExpansion bibleId ownership validation (TT-7681)', () => {\n beforeEach(() => {\n mockGetBibleMediaPlan.mockReset();\n mockGetBibleMediaPlan.mockResolvedValue({ id: 'plan-1' });\n });\n\n // Another team already owns this Bible Id. TeamDialog loads that team's\n // bible record into `bible` and flags `ownerName` once the id resolves,\n // which is why this prop shape (not our own team's bible) matters here.\n const foreignBible = {\n id: 'bible-other-team',\n type: 'bible',\n attributes: { bibleId: 'SEHICE', bibleName: '', description: '' },\n } as Bible;\n\n const renderWithForeignBible = (\n setValue: jest.Mock,\n overrides: { foreignOwner?: boolean; ownerName?: string } = {}\n ) =>\n render(\n \n );\n\n const lastBibleIdError = (setValue: jest.Mock): string | undefined =>\n setValue.mock.calls\n .filter(([what]) => what === 'bibleIdError')\n .map(([, value]) => value)\n .pop();\n\n const deleteAndRetypeLastChar = async () => {\n await waitFor(() => expect(capturedCanRecord).toBeDefined());\n\n const input = document.getElementById('bibleid') as HTMLInputElement;\n expect(input).toBeInTheDocument();\n expect(input.value).toBe('SEHICE');\n\n // Delete the last character, then retype it to restore the original,\n // still-foreign, Bible Id -- mirrors the steps in TT-7681.\n fireEvent.change(input, { target: { value: 'SEHIC' } });\n fireEvent.change(input, { target: { value: 'SEHICE' } });\n\n return input;\n };\n\n it('keeps the existing-bible error after deleting and retyping the last character', async () => {\n const setValue = jest.fn();\n renderWithForeignBible(setValue);\n const input = await deleteAndRetypeLastChar();\n\n expect(lastBibleIdError(setValue)).toBe(t.bibleidexists);\n expect(input).toHaveAttribute('aria-invalid', 'true');\n });\n\n // Devin finding: `ownerName` is only a display-name lookup and can be\n // undefined even when the bible is genuinely foreign-owned, e.g. the\n // owning team's `organization` record hasn't loaded locally (only its\n // Bible and organizationbible records are cached). Validation must not\n // treat a missing name as proof of ownership.\n it('keeps the existing-bible error when the foreign owner name has not loaded', async () => {\n const setValue = jest.fn();\n renderWithForeignBible(setValue, {\n foreignOwner: true,\n ownerName: undefined,\n });\n const input = await deleteAndRetypeLastChar();\n\n expect(lastBibleIdError(setValue)).toBe(t.bibleidexists);\n expect(input).toHaveAttribute('aria-invalid', 'true');\n });\n});\n\ndescribe('PublishExpansion owned bible id restore', () => {\n beforeEach(() => {\n mockGetBibleMediaPlan.mockReset();\n mockGetBibleMediaPlan.mockResolvedValue({ id: 'plan-1' });\n });\n\n const ownBible = {\n id: 'bible-own-team',\n type: 'bible',\n attributes: { bibleId: 'SEHSUS', bibleName: '', description: '' },\n } as Bible;\n\n const lastReportedBibleId = (setValue: jest.Mock): string | undefined =>\n setValue.mock.calls\n .filter(([what]) => what === 'bibleId')\n .map(([, value]) => value)\n .pop();\n\n it('reports the restored bible id after deleting and retyping the last character', async () => {\n const setValue = jest.fn();\n render(\n \n );\n await waitFor(() => expect(capturedCanRecord).toBeDefined());\n\n const input = document.getElementById('bibleid') as HTMLInputElement;\n expect(input.value).toBe('SEHSUS');\n\n // TeamDialog saves whatever bible id was last reported. Skipping the\n // report when the text matches the saved id leaves the parent on the\n // truncated value from the delete, and Save persists that.\n fireEvent.change(input, { target: { value: 'SEHSU' } });\n fireEvent.change(input, { target: { value: 'SEHSUS' } });\n\n expect(input.value).toBe('SEHSUS');\n expect(lastReportedBibleId(setValue)).toBe('SEHSUS');\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PublishExpansion.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getDefault', 'getPublishingData', and 'setLanguage'. Either include them or remove the dependency array.","line":150,"column":6,"nodeType":"ArrayExpression","endLine":150,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [team, bible, getPublishingData, getDefault, setLanguage]","fix":{"range":[4659,4672],"text":"[team, bible, getPublishingData, getDefault, setLanguage]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'bibleIdIsValid', 'onChanged', 'setBibleIdError', and 'setLanguage'. Either include them or remove the dependency array.","line":213,"column":5,"nodeType":"ArrayExpression","endLine":213,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [bibleId, bibleIdIsValid, onChanged, setBibleIdError, setLanguage]","fix":{"range":[6798,6807],"text":"[bibleId, bibleIdIsValid, onChanged, setBibleIdError, setLanguage]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'bibleId', 'bibleIdIsValid', and 'setBibleIdError'. Either include them or remove the dependency array.","line":246,"column":6,"nodeType":"ArrayExpression","endLine":246,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [bibleId, bibleIdIsValid, foreignOwner, setBibleIdError]","fix":{"range":[8280,8294],"text":"[bibleId, bibleIdIsValid, foreignOwner, setBibleIdError]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'showMessage', 't.planNotFound', and 't.projectRequired'. Either include them or remove the dependency array.","line":260,"column":6,"nodeType":"ArrayExpression","endLine":260,"endColumn":42,"suggestions":[{"desc":"Update the dependencies array to be: [loadBibleMediaPlan, projects, showMessage, t.planNotFound, t.projectRequired, team?.id]","fix":{"range":[8739,8775],"text":"[loadBibleMediaPlan, projects, showMessage, t.planNotFound, t.projectRequired, team?.id]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\PwaUpdatePrompt.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\RefLevel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\DialogModePartial.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\NoteTitle.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'noteSource'. Either include it or remove the dependency array.","line":38,"column":6,"nodeType":"ArrayExpression","endLine":38,"endColumn":10,"suggestions":[{"desc":"Update the dependencies array to be: [noteSource, ws]","fix":{"range":[1385,1389],"text":"[noteSource, ws]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResActionCol.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResRefTable.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'emptyRow', 'emptyTable', 'onCommit', and 'rowCells'. Either include them or remove the dependency array.","line":202,"column":6,"nodeType":"ArrayExpression","endLine":202,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [bookData, emptyRow, emptyTable, onCommit, rowCells]","fix":{"range":[5957,5967],"text":"[bookData, emptyRow, emptyTable, onCommit, rowCells]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResourceCategory.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResourceCategory.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResourceDescription.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResourceKeywords.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'allKeywords' and 'getOrgDefault'. Either include them or remove the dependency array.","line":25,"column":6,"nodeType":"ArrayExpression","endLine":25,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [allKeywords, getOrgDefault, org]","fix":{"range":[1055,1060],"text":"[allKeywords, getOrgDefault, org]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResourceLink.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 't.linkError'. Either include it or remove the dependency array.","line":29,"column":6,"nodeType":"ArrayExpression","endLine":29,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [linkurl, t.linkError]","fix":{"range":[962,971],"text":"[linkurl, t.linkError]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResourceOverview.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResourceOverview.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'ws'. Either include it or remove the dependency array.","line":164,"column":6,"nodeType":"ArrayExpression","endLine":164,"endColumn":41,"suggestions":[{"desc":"Update the dependencies array to be: [values, isOpen, isNote, initState, ws]","fix":{"range":[4345,4380],"text":"[values, isOpen, isNote, initState, ws]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'getOrgDefault' and 'setOrgDefault'. Either include them or remove the dependency array.","line":216,"column":6,"nodeType":"ArrayExpression","endLine":216,"endColumn":34,"suggestions":[{"desc":"Update the dependencies array to be: [keywords, canSetOrgDefault, getOrgDefault, setOrgDefault]","fix":{"range":[5970,5998],"text":"[keywords, canSetOrgDefault, getOrgDefault, setOrgDefault]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResourceRefs.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has missing dependencies: 'bookSort' and 'dataSort'. Either include them or remove the dependency array.","line":161,"column":6,"nodeType":"ArrayExpression","endLine":161,"endColumn":41,"suggestions":[{"desc":"Update the dependencies array to be: [sharedResourceReferences, dataSort, bookSort, res?.id]","fix":{"range":[5513,5548],"text":"[sharedResourceReferences, dataSort, bookSort, res?.id]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResourceTabs.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has missing dependencies: 'getSharedResource' and 'readSharedResource'. Either include them or remove the dependency array.","line":134,"column":5,"nodeType":"ArrayExpression","endLine":134,"endColumn":33,"suggestions":[{"desc":"Update the dependencies array to be: [getSharedResource, passId, readSharedResource, ws?.passage]","fix":{"range":[4357,4385],"text":"[getSharedResource, passId, readSharedResource, ws?.passage]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has unnecessary dependencies: 'passId' and 'sharedResources'. Either exclude them or remove the dependency array.","line":172,"column":6,"nodeType":"ArrayExpression","endLine":172,"endColumn":53,"suggestions":[{"desc":"Update the dependencies array to be: [isNote, sharedResRec]","fix":{"range":[5439,5486],"text":"[isNote, sharedResRec]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResourceTerms.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\ResourceTitle.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\SelectNote.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'bookSuggestions' and 'noteRefs'. Either include them or remove the dependency array.","line":82,"column":6,"nodeType":"ArrayExpression","endLine":82,"endColumn":21,"suggestions":[{"desc":"Update the dependencies array to be: [passage, data, bookSuggestions, noteRefs]","fix":{"range":[2711,2726],"text":"[passage, data, bookSuggestions, noteRefs]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":140,"column":5,"nodeType":"ArrayExpression","endLine":140,"endColumn":22,"suggestions":[{"desc":"Update the dependencies array to be: [bookCd, findRef, memory]","fix":{"range":[4697,4714],"text":"[bookCd, findRef, memory]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'planType'. Either include it or remove the dependency array.","line":145,"column":6,"nodeType":"ArrayExpression","endLine":145,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [plan, planType]","fix":{"range":[4881,4887],"text":"[plan, planType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getNotes'. Either include it or remove the dependency array.","line":160,"column":6,"nodeType":"ArrayExpression","endLine":160,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [getNotes, refLevel, refRes]","fix":{"range":[5429,5447],"text":"[getNotes, refLevel, refRes]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'localizedArtifactCategory', 'memory', 'noteSource', 't.no', and 't.yes'. Either include them or remove the dependency array.","line":193,"column":6,"nodeType":"ArrayExpression","endLine":193,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [localizedArtifactCategory, memory, noteSource, notes, t.no, t.yes]","fix":{"range":[6547,6554],"text":"[localizedArtifactCategory, memory, noteSource, notes, t.no, t.yes]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\ResourceEdit\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\RoleAvatar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\RoleIcons.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\ArtCatScr.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\AudacityManager.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'allBookData', 'audRead', 'getPassage', and 'name'. Either include them or remove the dependency array.","line":340,"column":6,"nodeType":"ArrayExpression","endLine":340,"endColumn":21,"suggestions":[{"desc":"Update the dependencies array to be: [allBookData, audRead, getPassage, name, passageId.id]","fix":{"range":[9948,9963],"text":"[allBookData, audRead, getPassage, name, passageId.id]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'nameUpdate'. Either include it or remove the dependency array.","line":350,"column":6,"nodeType":"ArrayExpression","endLine":350,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [name, nameUpdate]","fix":{"range":[10179,10185],"text":"[name, nameUpdate]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\GraphicAvatar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\NewArtifactCategory.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\OrgWorkflowStepList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PassageCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PassageGraphic.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PassageRef.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PlanActionMenu.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-refresh/only-export-components').","line":25,"column":1,"severity":1,"nodeType":null,"fix":{"range":[843,907],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"The ref value 'anchorRef.current' will likely have changed by the time this effect cleanup function runs. If this ref points to a node rendered by React, copy 'anchorRef.current' to a variable inside the effect, and use that variable in the cleanup function.","line":123,"column":19,"nodeType":"Identifier","endLine":123,"endColumn":26,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'handleMove' and 'handleOver'. Either include them or remove the dependency array.","line":127,"column":6,"nodeType":"ArrayExpression","endLine":127,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [handleMove, handleOver]","fix":{"range":[3903,3905],"text":"[handleMove, handleOver]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable react-hooks/exhaustive-deps */\nimport React from 'react';\nimport {\n ISharedStrings,\n IPlanActionsStrings,\n IPlanSheetStrings,\n IPassageTypeStrings,\n} from '../../model';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport { Box, Popper, Grow, Paper, ClickAwayListener } from '@mui/material';\nimport MoreIcon from '@mui/icons-material/MoreHoriz';\nimport { elemOffset } from '../../utils';\nimport {\n passageTypeSelector,\n planActionsSelector,\n planSheetSelector,\n sharedSelector,\n} from '../../selector';\nimport { PlanMoreMenuItems } from './PlanMoreMenuItems';\nimport { ExtraIcon } from '.';\nimport { Button } from '../../control/Button';\n\n/** Live row selection — menus consume this so they close without a grid refill. */\n// only PlanActionMenu reads this; a split file would exist only for Fast Refresh\n// eslint-disable-next-line react-refresh/only-export-components\nexport const PlanSheetRowCtx = React.createContext({\n currentRow: -1,\n activeRow: -1,\n sheetCurrentI: -1,\n clearActive: () => {},\n});\n\ninterface IProps {\n rowIndex: number;\n isSection: boolean;\n isPassage: boolean;\n psgType: string;\n readonly: boolean;\n canAssign: boolean;\n canDelete: boolean;\n organizedBy: string;\n sectionSequenceNumber: string;\n passageSequenceNumber: string;\n firstMovement: number;\n onPlayStatus: (mediaId: string) => void;\n onUpload: (i: number) => () => void;\n onAssign: (where: number[]) => () => void;\n onDelete: (i: number) => () => void;\n onFirstMovement: (i: number, fm: number) => void;\n onDisableFilter?: () => void;\n showIcon: (icon: ExtraIcon) => boolean;\n onAction: (i: number, what: ExtraIcon) => void;\n}\nexport function PlanActionMenu(props: IProps) {\n const { rowIndex } = props;\n const { currentRow, activeRow, clearActive } =\n React.useContext(PlanSheetRowCtx);\n const t: IPlanActionsStrings = useSelector(planActionsSelector, shallowEqual);\n const p: IPlanSheetStrings = useSelector(planSheetSelector, shallowEqual);\n const ts: ISharedStrings = useSelector(sharedSelector, shallowEqual);\n const ty: IPassageTypeStrings = useSelector(\n passageTypeSelector,\n shallowEqual\n );\n const [open, setOpen] = React.useState(false);\n const [hover, setHover] = React.useState(false);\n const top = React.useRef(0);\n const height = React.useRef(0);\n const anchorRef = React.useRef(null);\n const menuRef = React.useRef(null);\n\n const handleToggle = () => {\n setOpen((prevOpen) => !prevOpen);\n };\n\n const handleClose = (event: MouseEvent | TouchEvent) => {\n if (\n anchorRef.current &&\n anchorRef.current.contains(event.target as HTMLElement)\n ) {\n return;\n }\n\n setOpen(false);\n };\n\n function onKey(event: React.KeyboardEvent) {\n if (event.key === 'Tab') {\n event.preventDefault();\n setOpen(false);\n } else if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {\n event.stopPropagation();\n } else if (event.key === 'Escape') {\n setHover(false);\n setOpen(false);\n }\n }\n\n const handleMove = (event: MouseEvent) => {\n const y = event.pageY;\n if (y < top.current || y > top.current + height.current) {\n setHover(false);\n window.removeEventListener('mouseover', handleMove);\n }\n };\n\n const handleOver = () => {\n setHover(true);\n if (menuRef.current) {\n const { y } = elemOffset(menuRef.current);\n top.current = y;\n height.current = menuRef.current?.clientHeight;\n window.addEventListener('mouseover', handleMove);\n }\n };\n\n React.useEffect(() => {\n if (anchorRef.current) {\n anchorRef.current.addEventListener('mouseover', handleOver);\n }\n return () => {\n if (anchorRef.current) {\n anchorRef.current.removeEventListener('mouseover', handleOver);\n }\n window.removeEventListener('mouseover', handleMove);\n };\n }, []);\n\n // return focus to the button when we transitioned from !open -> open\n const prevOpen = React.useRef(open);\n React.useEffect(() => {\n if (prevOpen.current === true && open === false) {\n if (currentRow < 1 || currentRow - 1 === rowIndex) {\n anchorRef.current?.focus();\n }\n }\n\n prevOpen.current = open;\n }, [open, currentRow, rowIndex]);\n\n React.useEffect(() => {\n if (activeRow > 0 && activeRow - 1 === rowIndex) setOpen(true);\n }, [activeRow, rowIndex]);\n\n React.useEffect(() => {\n if (currentRow >= 1 && currentRow - 1 !== rowIndex) {\n setOpen(false);\n setHover(false);\n clearActive();\n }\n }, [currentRow, rowIndex, clearActive]);\n\n React.useEffect(() => {\n const tr = menuRef.current?.closest('tr');\n if (!tr) return;\n const leave = (e: MouseEvent) => {\n if (tr.contains(e.relatedTarget as Node)) return;\n setOpen(false);\n setHover(false);\n clearActive();\n };\n tr.addEventListener('mouseleave', leave);\n return () => tr.removeEventListener('mouseleave', leave);\n }, [clearActive]);\n\n return (\n \n
\n \n \n \n \n {({ TransitionProps, placement }) => (\n \n \n \n \n \n \n \n )}\n \n
\n
\n );\n}\n\nexport default PlanActionMenu;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PlanAudioActions.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PlanBar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PlanMoreMenuItems.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PlanPublishActions.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PlanSheet.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'setCurrentRow'. Either include it or remove the dependency array.","line":1054,"column":6,"nodeType":"ArrayExpression","endLine":1067,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [filtered, goToQuery, hidePublishing, inlinePassages, lookupBook, publishingOn, rowInfo, scripture, sectionArr, setCurrentRow, showMessage, t.referenceFilteredNoPublishingLabels, t.referenceNotFound]","fix":{"range":[32440,32677],"text":"[filtered, goToQuery, hidePublishing, inlinePassages, lookupBook, publishingOn, rowInfo, scripture, sectionArr, setCurrentRow, showMessage, t.referenceFilteredNoPublishingLabels, t.referenceNotFound]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'handleRowsPerPage', 'scrolled', 'subscribe', 'syncViewport', and 'unsubscribe'. Either include them or remove the dependency array.","line":1153,"column":6,"nodeType":"ArrayExpression","endLine":1153,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [handleRowsPerPage, scrolled, subscribe, syncViewport, unsubscribe]","fix":{"range":[35373,35375],"text":"[handleRowsPerPage, scrolled, subscribe, syncViewport, unsubscribe]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'memory?.keyMap' and 'setCurrentRow'. Either include them or remove the dependency array.","line":1184,"column":6,"nodeType":"ArrayExpression","endLine":1184,"endColumn":35,"suggestions":[{"desc":"Update the dependencies array to be: [rowInfo, toRow, data.length, memory?.keyMap, setCurrentRow]","fix":{"range":[36222,36251],"text":"[rowInfo, toRow, data.length, memory?.keyMap, setCurrentRow]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'changed', 'checkOnline', 'clearCompleted', 'clearRequested', 'connected', 'isChanged', 'offlineOnly', 'saveRequested', 'saving', 'showMessage', 'startSaveTimer', 'toolId', and 'ts.NoSaveOffline'. Either include them or remove the dependency array.","line":1213,"column":6,"nodeType":"ArrayExpression","endLine":1213,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [changed, checkOnline, clearCompleted, clearRequested, connected, isChanged, offlineOnly, saveRequested, saving, showMessage, startSaveTimer, toolId, toolsChanged, ts.NoSaveOffline]","fix":{"range":[37165,37179],"text":"[changed, checkOnline, clearCompleted, clearRequested, connected, isChanged, offlineOnly, saveRequested, saving, showMessage, startSaveTimer, toolId, toolsChanged, ts.NoSaveOffline]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'colSlugs', 'planSheetFill', and 'warningTest'. Either include them or remove the dependency array.","line":1269,"column":6,"nodeType":"ArrayExpression","endLine":1285,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [rowData, rowInfo, columns, srcMediaId, mediaPlaying, filtered, check, anyRecording, firstMovement, sectionArr, hidePublishing, publishingOn, canEditSheet, canPublish, shared, planSheetFill, colSlugs, warningTest]","fix":{"range":[38828,39068],"text":"[rowData, rowInfo, columns, srcMediaId, mediaPlaying, filtered, check, anyRecording, firstMovement, sectionArr, hidePublishing, publishingOn, canEditSheet, canPublish, shared, planSheetFill, colSlugs, warningTest]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'isSectionType'. Either include it or remove the dependency array.","line":1313,"column":6,"nodeType":"ArrayExpression","endLine":1313,"endColumn":36,"suggestions":[{"desc":"Update the dependencies array to be: [isSectionType, rowData]","fix":{"range":[39961,39991],"text":"[isSectionType, rowData]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'isPassageType'. Either include it or remove the dependency array.","line":1326,"column":5,"nodeType":"ArrayExpression","endLine":1326,"endColumn":51,"suggestions":[{"desc":"Update the dependencies array to be: [isPassageType, rowInfo]","fix":{"range":[40423,40469],"text":"[isPassageType, rowInfo]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has an unnecessary dependency: 'currentRow'. Either exclude it or remove the dependency array.","line":1339,"column":5,"nodeType":"ArrayExpression","endLine":1339,"endColumn":26,"suggestions":[{"desc":"Update the dependencies array to be: [rowInfo]","fix":{"range":[40866,40887],"text":"[rowInfo]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'isSectionType'. Either include it or remove the dependency array.","line":1344,"column":6,"nodeType":"ArrayExpression","endLine":1344,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [currentRow, isSectionType]","fix":{"range":[41043,41055],"text":"[currentRow, isSectionType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useLayoutEffect has a missing dependency: 'syncViewport'. Either include it or remove the dependency array.","line":1364,"column":6,"nodeType":"ArrayExpression","endLine":1364,"endColumn":30,"suggestions":[{"desc":"Update the dependencies array to be: [data.length, rowHeight, syncViewport]","fix":{"range":[41700,41724],"text":"[data.length, rowHeight, syncViewport]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PlanTabSelect.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PlanView.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\PublishButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\ScriptureTable.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'getProjectDefault'. Either include it or remove the dependency array.","line":395,"column":5,"nodeType":"ArrayExpression","endLine":395,"endColumn":23,"suggestions":[{"desc":"Update the dependencies array to be: [getProjectDefault, scripture, sheet]","fix":{"range":[13564,13582],"text":"[getProjectDefault, scripture, sheet]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has an unnecessary dependency: 'sheet'. Either exclude it or remove the dependency array.","line":399,"column":69,"nodeType":"ArrayExpression","endLine":399,"endColumn":76,"suggestions":[{"desc":"Update the dependencies array to be: []","fix":{"range":[13715,13722],"text":"[]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'defaultFilterState.minSection'. Either include it or remove the dependency array.","line":409,"column":6,"nodeType":"ArrayExpression","endLine":409,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [defaultFilterState.minSection, minSection]","fix":{"range":[14067,14079],"text":"[defaultFilterState.minSection, minSection]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'getGlobal' and 'setCanAddPublishing'. Either include them or remove the dependency array.","line":508,"column":5,"nodeType":"ArrayExpression","endLine":508,"endColumn":25,"suggestions":[{"desc":"Update the dependencies array to be: [getGlobal, publishingOn, setCanAddPublishing, flat]","fix":{"range":[17013,17033],"text":"[getGlobal, publishingOn, setCanAddPublishing, flat]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getFilter'. Either include it or remove the dependency array.","line":1477,"column":6,"nodeType":"ArrayExpression","endLine":1477,"endColumn":47,"suggestions":[{"desc":"Update the dependencies array to be: [project, defaultFilterState, showAssign, getFilter]","fix":{"range":[46308,46349],"text":"[project, defaultFilterState, showAssign, getFilter]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getProjectDefault'. Either include it or remove the dependency array.","line":1483,"column":6,"nodeType":"ArrayExpression","endLine":1483,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [getProjectDefault, project]","fix":{"range":[46569,46578],"text":"[getProjectDefault, project]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'anySaving', 'checkOnline', 'clearCompleted', 'clearRequested', 'doDetachMedia', 'firstMovement', 'forceDataChanges', 'isChanged', 'lastSaved', 'localSave', 'memory.cache', 'offlineOnly', 'onlineSave', 'projFirstMovement', 'saveCompleted', 'saveRequested', 'setBusy', 'setChanged', 'setComplete', 'setLastSaved', 'setProjectDefault', 'setUpdate', 'showMessage', 't.publishingWarning', 't.saving', 'ts.NoSaveOffline', 'ts.NoSaveWoMedia', 'ts.TooBusy', 'updateLastModified', and 'waitForRemoteQueue'. Either include them or remove the dependency array.","line":1717,"column":6,"nodeType":"ArrayExpression","endLine":1717,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [anySaving, checkOnline, clearCompleted, clearRequested, doDetachMedia, firstMovement, forceDataChanges, isChanged, lastSaved, localSave, memory.cache, offlineOnly, onlineSave, projFirstMovement, saveCompleted, saveRequested, setBusy, setChanged, setComplete, setLastSaved, setProjectDefault, setUpdate, showMessage, t.publishingWarning, t.saving, toolsChanged, ts.NoSaveOffline, ts.NoSaveWoMedia, ts.TooBusy, updateLastModified, waitForRemoteQueue]","fix":{"range":[53647,53661],"text":"[anySaving, checkOnline, clearCompleted, clearRequested, doDetachMedia, firstMovement, forceDataChanges, isChanged, lastSaved, localSave, memory.cache, offlineOnly, onlineSave, projFirstMovement, saveCompleted, saveRequested, setBusy, setChanged, setComplete, setLastSaved, setProjectDefault, setUpdate, showMessage, t.publishingWarning, t.saving, toolsChanged, ts.NoSaveOffline, ts.NoSaveWoMedia, ts.TooBusy, updateLastModified, waitForRemoteQueue]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'allBookData.length', 'fetchBooks', and 'refreshSheet'. Either include them or remove the dependency array.","line":1731,"column":6,"nodeType":"ArrayExpression","endLine":1750,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [organizationSchemeSteps, plan, sections, passages, mediafiles, graphics, sharedresources, discussions, groupmemberships, flat, shared, orgSteps, lastSaved, hidePublishing, scripture, lang, allBookData.length, fetchBooks, refreshSheet]","fix":{"range":[54007,54416],"text":"[organizationSchemeSteps, plan, sections, passages, mediafiles, graphics, sharedresources, discussions, groupmemberships, flat, shared, orgSteps, lastSaved, hidePublishing, scripture, lang, allBookData.length, fetchBooks, refreshSheet]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'columns', 'local', and 'saveColAdd'. Either include them or remove the dependency array.","line":1785,"column":6,"nodeType":"ArrayExpression","endLine":1785,"endColumn":42,"suggestions":[{"desc":"Update the dependencies array to be: [sheet, width, colNames, flat, lang, local, saveColAdd, columns]","fix":{"range":[55270,55306],"text":"[sheet, width, colNames, flat, lang, local, saveColAdd, columns]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'minSection', 'myGroups', 'setSheet', 'setUpdate', and 'user'. Either include them or remove the dependency array.","line":1807,"column":6,"nodeType":"ArrayExpression","endLine":1807,"endColumn":63,"suggestions":[{"desc":"Update the dependencies array to be: [orgSteps, filterState, doneStepId, hidePublishing, flat, setUpdate, minSection, user, myGroups, setSheet]","fix":{"range":[55784,55841],"text":"[orgSteps, filterState, doneStepId, hidePublishing, flat, setUpdate, minSection, user, myGroups, setSheet]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'bookSortMap', 'getProjectDefault', 'setProjectDefault', and 'updateBook'. Either include them or remove the dependency array.","line":1835,"column":6,"nodeType":"ArrayExpression","endLine":1835,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [bookSortMap, firstBook, getProjectDefault, scripture, setProjectDefault, updateBook]","fix":{"range":[56790,56812],"text":"[bookSortMap, firstBook, getProjectDefault, scripture, setProjectDefault, updateBook]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'local'. Either include it or remove the dependency array.","line":2169,"column":6,"nodeType":"ArrayExpression","endLine":2169,"endColumn":79,"suggestions":[{"desc":"Update the dependencies array to be: [sheet, publishingOn, hidePublishing, local, organizedBy]","fix":{"range":[66735,66808],"text":"[sheet, publishingOn, hidePublishing, local, organizedBy]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\SelectArtifactCategory.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getCategorys'. Either include it or remove the dependency array.","line":129,"column":6,"nodeType":"ArrayExpression","endLine":129,"endColumn":48,"suggestions":[{"desc":"Update the dependencies array to be: [artifactCategories, scripture, org, type, getCategorys]","fix":{"range":[4002,4044],"text":"[artifactCategories, scripture, org, type, getCategorys]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\SelectArtifactType.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getArtifactTypes'. Either include it or remove the dependency array.","line":45,"column":6,"nodeType":"ArrayExpression","endLine":45,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [getArtifactTypes, limit]","fix":{"range":[1490,1497],"text":"[getArtifactTypes, limit]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'artifactType'. Either include it or remove the dependency array.","line":53,"column":6,"nodeType":"ArrayExpression","endLine":53,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [artifactType, initialValue]","fix":{"range":[1749,1763],"text":"[artifactType, initialValue]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\TitleEdit.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\audioTypes.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\extraIcon.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\filterMenu.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\findPlanSheetRowFromReferenceQuery.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\findPlanSheetRowFromReferenceQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\getDefaultName.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\getPubRefs.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\getSheet.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\isSectionPassage.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\isSectionPassageUpdated.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\noteCategoryRef.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\noteCategoryRef.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\pendingTitleMediaQueue.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\pendingTitleMediaQueue.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\refilterSheet.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\resolveSheetStartChapter.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\resolveSheetStartChapter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\resolveTitleMediaRowIndex.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\resolveTitleMediaRowIndex.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\rowTypes.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\runTitleMediaUpdate.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\runTitleMediaUpdate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\sheetWindow.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\sheetWindow.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\shtColumnHeads.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\shtNumChanges.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\shtResequence.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\usePlanSheetFill.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'getOrganizedBy'. Either include it or remove the dependency array.","line":196,"column":59,"nodeType":"ArrayExpression","endLine":196,"endColumn":67,"suggestions":[{"desc":"Update the dependencies array to be: [getOrganizedBy]","fix":{"range":[7192,7200],"text":"[getOrganizedBy]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'onSetPreventSave'. Either include it or remove the dependency array.","line":212,"column":5,"nodeType":"ArrayExpression","endLine":212,"endColumn":50,"suggestions":[{"desc":"Update the dependencies array to be: [bookSuggestions, canEditSheet, onSetPreventSave, t.bookSelect]","fix":{"range":[7623,7668],"text":"[bookSuggestions, canEditSheet, onSetPreventSave, t.bookSelect]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\useRefErrTest.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\useSectionIdDescription.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\useSectionIdDescription.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\useSheetLocalSave.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\useSheetOnlineSave.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\useSheetPaste.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\useShowIcon.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\withUpdatedReference.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\withUpdatedReference.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Sheet\\workSheet.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\SpeakerName.test.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":1,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":1,"endColumn":13}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import React, { useState } from 'react';\nimport { fireEvent, render, screen } from '@testing-library/react';\nimport { ThemeProvider, createTheme } from '@mui/material/styles';\nimport SpeakerName from './SpeakerName';\n\njest.mock('../context/useGlobal', () => ({\n useGlobal: (key: string) => {\n if (key === 'organization') return ['org1', jest.fn()];\n if (key === 'memory') return [{}, jest.fn()];\n return [undefined, jest.fn()];\n },\n}));\n\njest.mock('../hoc/useOrbitData', () => ({\n useOrbitData: () => [{ attributes: { rightsHolder: 'Alice' } }],\n}));\n\njest.mock('../hoc/SnackBar', () => ({\n useSnackBar: () => ({ showMessage: jest.fn() }),\n}));\n\njest.mock('../crud', () => ({\n ArtifactTypeSlug: { IntellectualProperty: 'intellectualproperty' },\n findRecord: jest.fn(),\n related: () => 'org1',\n}));\n\njest.mock('react-redux', () => ({\n useSelector: () => ({\n selectSpeaker: 'Select Speaker',\n addSpeaker: 'Add {0}',\n speaker: 'Speaker',\n noVoiceCreation: 'No voice creation',\n voiceRights: 'Voice rights',\n releaseRights: 'Release rights',\n cancel: 'Cancel',\n }),\n shallowEqual: (a: unknown, b: unknown) => a === b,\n}));\n\njest.mock('./ProvideRights', () => () => null);\n\nconst theme = createTheme();\n\n/** Same rights-gate MediaUploadContent uses for the upload-audio speaker field. */\nfunction UploadSpeakerField() {\n const [speaker, setSpeaker] = useState('');\n const [hasRights, setHasRights] = useState(false);\n return (\n \n );\n}\n\nfunction renderUploadSpeaker() {\n return render(\n \n \n \n );\n}\n\ndescribe('SpeakerName upload dialog (mobile)', () => {\n it('shows the chosen existing speaker after select (rights-gated name)', async () => {\n renderUploadSpeaker();\n\n fireEvent.click(screen.getByRole('button', { name: 'Select Speaker...' }));\n\n fireEvent.mouseDown(screen.getByRole('combobox'));\n fireEvent.click(await screen.findByRole('option', { name: 'Alice' }));\n\n expect(\n await screen.findByRole('button', { name: 'Alice' })\n ).toBeInTheDocument();\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\SpeakerName.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'inList' and 'onRights'. Either include them or remove the dependency array. If 'onRights' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":203,"column":6,"nodeType":"ArrayExpression","endLine":203,"endColumn":22,"suggestions":[{"desc":"Update the dependencies array to be: [speakers, name, inList, onRights]","fix":{"range":[6179,6195],"text":"[speakers, name, inList, onRights]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\SpellCustomList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\SpellLanguagePicker.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":45,"column":5,"severity":1,"nodeType":null,"fix":{"range":[1123,1178],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import React from 'react';\nimport {\n List,\n ListItemButton,\n ListItemIcon,\n ListItemText,\n Checkbox,\n} from '@mui/material';\nimport { useLocLangName } from '../utils/useLocLangName';\nimport { MainAPI } from '@model/main-api';\nconst ipc = window?.api as MainAPI;\n\ninterface IProps {\n onSetCodes?: (codes: string[]) => void;\n}\n\nexport const SpellLanguagePicker = (props: IProps) => {\n const { onSetCodes } = props;\n const [checked, setChecked] = React.useState([]);\n const [codes, setCodes] = React.useState([]);\n const [getName, compare] = useLocLangName();\n\n const handleToggle = (value: string) => () => {\n const currentIndex = checked.indexOf(value);\n const newChecked = [...checked];\n\n if (currentIndex === -1) {\n newChecked.push(value);\n } else {\n newChecked.splice(currentIndex, 1);\n }\n onSetCodes && onSetCodes(newChecked);\n setChecked(newChecked);\n };\n\n React.useEffect(() => {\n ipc?.availSpellLangs().then((list: string[]) => {\n setCodes(list);\n });\n\n ipc?.getSpellLangs().then((list: string[]) => {\n setChecked(list);\n });\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n \n {codes.sort(compare).map((value) => {\n const labelId = `checkbox-list-label-${value}`;\n\n return (\n \n \n \n \n \n \n );\n })}\n \n );\n};\n\nexport default SpellLanguagePicker;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Spelling.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 't.addToDict'. Either include it or remove the dependency array.","line":50,"column":6,"nodeType":"ArrayExpression","endLine":50,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [t.addToDict]","fix":{"range":[1408,1410],"text":"[t.addToDict]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\SpellingTabs.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\DiscussStepSettings.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":30,"column":5,"severity":1,"nodeType":null,"fix":{"range":[898,953],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { useEffect, useState } from 'react';\nimport { MarkDownEdit } from '../../control/MarkDownEdit';\nimport { Box } from '@mui/material';\nimport { Button, ActionRow, rowSx } from '../../control';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport { sharedSelector } from '../../selector';\nimport { ISharedStrings } from '../../model';\n\ninterface IProps {\n toolSettings: string;\n onChange: (toolSettings: string) => void;\n onClose: () => void;\n}\n\nexport const DiscussStepSettings = ({\n toolSettings,\n onChange,\n onClose,\n}: IProps) => {\n const [inValue, setInValue] = useState('');\n const [value, setValue] = useState('');\n const ts: ISharedStrings = useSelector(sharedSelector, shallowEqual);\n\n useEffect(() => {\n if (toolSettings) {\n const json = JSON.parse(toolSettings);\n setValue(json.markDown);\n setInValue(json.markDown);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [toolSettings]);\n\n const handleChange = (value: string | null) => {\n setValue(value || '');\n };\n\n const handleSave = () => {\n onChange(JSON.stringify({ markDown: value }));\n onClose();\n };\n\n return (\n \n \n \n \n \n \n {ts.save}\n \n \n \n \n );\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\ParatextStepSettings.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":23,"column":5,"severity":1,"nodeType":null,"fix":{"range":[720,775],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { useEffect, useState } from 'react';\nimport { ArtifactTypeSlug } from '../../crud';\nimport SelectArtifactType from '../Sheet/SelectArtifactType';\n\ninterface IProps {\n toolSettings: string;\n onChange: (toolSettings: string) => void;\n}\n\nexport const ParatextStepSettings = ({ toolSettings, onChange }: IProps) => {\n // const classes = useStyles();\n const artifacts = [\n ArtifactTypeSlug.Vernacular,\n ArtifactTypeSlug.WholeBackTranslation,\n ArtifactTypeSlug.PhraseBackTranslation,\n ];\n const [initialValue, setInitialValue] = useState(null);\n useEffect(() => {\n if (toolSettings) {\n const json = JSON.parse(toolSettings);\n setInitialValue(json.artifactTypeId);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [toolSettings]);\n const handleSelect = (artifactTypeId: string | null) => {\n onChange(JSON.stringify({ artifactTypeId: artifactTypeId }));\n };\n\n return (\n \n );\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\PhraseBackTranslateStepSettings.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'props'. Either include it or remove the dependency array. However, 'props' will change when *any* prop changes, so the preferred fix is to destructure the 'props' object outside of the useEffect call and refer to those specific props inside React.useEffect.","line":116,"column":10,"nodeType":"ArrayExpression","endLine":116,"endColumn":33,"suggestions":[{"desc":"Update the dependencies array to be: [state, props.onChange, props]","fix":{"range":[3641,3664],"text":"[state, props.onChange, props]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\PhraseBackTranslateStepSettings.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\RecordStepSettings.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\StepEditor.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'se.stepsHidden'. Either include it or remove the dependency array.","line":134,"column":5,"nodeType":"ArrayExpression","endLine":134,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [hidden, se.stepsHidden]","fix":{"range":[4176,4184],"text":"[hidden, se.stepsHidden]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearCompleted', 'clearRequested', 'saveCompleted', 'saveRecs', and 'saveRequested'. Either include them or remove the dependency array.","line":433,"column":6,"nodeType":"ArrayExpression","endLine":433,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [clearCompleted, clearRequested, saveCompleted, saveRecs, saveRequested, toolsChanged]","fix":{"range":[12759,12773],"text":"[clearCompleted, clearRequested, saveCompleted, saveRecs, saveRequested, toolsChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'GetOrgWorkflowSteps', 'localizedWorkStep', and 'prettySettings'. Either include them or remove the dependency array.","line":468,"column":6,"nodeType":"ArrayExpression","endLine":468,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [GetOrgWorkflowSteps, localizedWorkStep, org, prettySettings]","fix":{"range":[13890,13895],"text":"[GetOrgWorkflowSteps, localizedWorkStep, org, prettySettings]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\StepItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\StepName.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":29,"column":5,"severity":1,"nodeType":null,"fix":{"range":[989,1044],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { IStepEditorStrings } from '../../model';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport { TextField } from '@mui/material';\nimport { useEffect, useRef, useState } from 'react';\nimport { stepEditorSelector } from '../../selector';\n\ninterface IProps {\n name: string;\n pos: number;\n isFocused: boolean;\n onChange: (name: string, pos: number) => void;\n}\n\nexport const StepName = ({ name, pos, isFocused, onChange }: IProps) => {\n const [response, setResponse] = useState(name);\n const elRef = useRef(null);\n const t: IStepEditorStrings = useSelector(stepEditorSelector, shallowEqual);\n\n const handleChange = (e: React.ChangeEvent) => {\n const name = e.target.value;\n setResponse(name);\n onChange(name, e.target.selectionStart || 0);\n };\n\n useEffect(() => {\n setResponse(name);\n const input = elRef.current?.childNodes[1]?.firstChild as HTMLInputElement;\n if (input) input.setSelectionRange(pos, pos);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [name, pos]);\n\n return (\n \n );\n};\n\nexport default StepName;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\ToolChoice.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\TranscribeStepSettings.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getOrgDefault', 'org', 'readVernacularFromOrg', and 'slugFromId'. Either include them or remove the dependency array.","line":348,"column":6,"nodeType":"ArrayExpression","endLine":348,"endColumn":37,"suggestions":[{"desc":"Update the dependencies array to be: [toolSettings, availSpellLangs, slugFromId, org, readVernacularFromOrg, getOrgDefault]","fix":{"range":[10379,10410],"text":"[toolSettings, availSpellLangs, slugFromId, org, readVernacularFromOrg, getOrgDefault]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'readVernacularFromOrg'. Either include it or remove the dependency array.","line":396,"column":6,"nodeType":"ArrayExpression","endLine":396,"endColumn":32,"suggestions":[{"desc":"Update the dependencies array to be: [isOpen, currentSlug, org, readVernacularFromOrg]","fix":{"range":[12102,12128],"text":"[isOpen, currentSlug, org, readVernacularFromOrg]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchRecommendations', 'persistRecommendations', 'readCachedRecommendations', 'reset', and 'seedSuggestions'. Either include them or remove the dependency array.","line":482,"column":6,"nodeType":"ArrayExpression","endLine":482,"endColumn":59,"suggestions":[{"desc":"Update the dependencies array to be: [showSisterLanguage, primaryLanguageName, primaryIso, readCachedRecommendations, seedSuggestions, fetchRecommendations, persistRecommendations, reset]","fix":{"range":[14831,14884],"text":"[showSisterLanguage, primaryLanguageName, primaryIso, readCachedRecommendations, seedSuggestions, fetchRecommendations, persistRecommendations, reset]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\isDuplicatePhraseBtLanguage.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StepEditor\\isDuplicatePhraseBtLanguage.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StickyRedirect.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'navigate' and 'pathname'. Either include them or remove the dependency array.","line":28,"column":6,"nodeType":"ArrayExpression","endLine":28,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [memory, navigate, pathname, reporter, to]","fix":{"range":[842,864],"text":"[memory, navigate, pathname, reporter, to]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\StyledDialogTitle.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TaskAvatar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TaskFlag.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TaskList.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'heightAdjust' and 'widthAdjust'. Either include them or remove the dependency array.","line":66,"column":6,"nodeType":"ArrayExpression","endLine":66,"endColumn":39,"suggestions":[{"desc":"Update the dependencies array to be: [pdBusy, loading, discussionSize, widthAdjust, heightAdjust]","fix":{"range":[2408,2441],"text":"[pdBusy, loading, discussionSize, widthAdjust, heightAdjust]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getPlan'. Either include it or remove the dependency array.","line":78,"column":6,"nodeType":"ArrayExpression","endLine":78,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [getPlan, planId]","fix":{"range":[2775,2783],"text":"[getPlan, planId]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\AddCard.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getOrgDefault', 'setLanguage', and 'team?.id'. Either include them or remove the dependency array.","line":75,"column":6,"nodeType":"ArrayExpression","endLine":75,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, setLanguage, team?.id]","fix":{"range":[2565,2567],"text":"[getOrgDefault, setLanguage, team?.id]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\CardSize.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\CategoryEdit.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\CategoryEdit.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'graphicRec?.id' and 'memory?.keyMap'. Either include them or remove the dependency array.","line":182,"column":8,"nodeType":"ArrayExpression","endLine":182,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [category, graphicRec?.id, graphics, memory?.keyMap]","fix":{"range":[5792,5812],"text":"[category, graphicRec?.id, graphics, memory?.keyMap]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\CategoryListEdit.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\CategoryListEdit.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getBibleMediaPlan'. Either include it or remove the dependency array.","line":87,"column":6,"nodeType":"ArrayExpression","endLine":87,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [getBibleMediaPlan]","fix":{"range":[3155,3157],"text":"[getBibleMediaPlan]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getArtifactCategorys'. Either include it or remove the dependency array.","line":160,"column":6,"nodeType":"ArrayExpression","endLine":160,"endColumn":41,"suggestions":[{"desc":"Update the dependencies array to be: [type, refresh, artifactCategories, getArtifactCategorys]","fix":{"range":[5329,5364],"text":"[type, refresh, artifactCategories, getArtifactCategorys]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'showMessage' and 'tc.editRemoved'. Either include them or remove the dependency array.","line":185,"column":6,"nodeType":"ArrayExpression","endLine":185,"endColumn":32,"suggestions":[{"desc":"Update the dependencies array to be: [orgCategories, editingId, showMessage, tc.editRemoved]","fix":{"range":[6466,6492],"text":"[orgCategories, editingId, showMessage, tc.editRemoved]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\CategoryTabs.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\FeatureSlug.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\PendingUploadsDialog.retry.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":76,"column":32,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":76,"endColumn":69,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":218,"column":7,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":218,"endColumn":56,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":246,"column":29,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":246,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":246,"column":57,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":246,"endColumn":73,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":250,"column":19,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":250,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":252,"column":7,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":252,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":254,"column":7,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":254,"endColumn":40,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\PendingUploadsDialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\PersonalItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectCard.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'doOpen'. Either include it or remove the dependency array.","line":180,"column":6,"nodeType":"ArrayExpression","endLine":180,"endColumn":23,"suggestions":[{"desc":"Update the dependencies array to be: [projectId, open, doOpen]","fix":{"range":[6237,6254],"text":"[projectId, open, doOpen]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'localizedOrganizedBy' and 'userIsOrgAdmin'. Either include them or remove the dependency array.","line":191,"column":6,"nodeType":"ArrayExpression","endLine":191,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [localizedOrganizedBy, project, userIsOrgAdmin]","fix":{"range":[6604,6613],"text":"[localizedOrganizedBy, project, userIsOrgAdmin]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'copyComplete', 'copying', 'forceDataChanges', 'setBusy', 'showMessage', 't.copyComplete', and 'tt.downloading'. Either include them or remove the dependency array.","line":216,"column":6,"nodeType":"ArrayExpression","endLine":216,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [copyComplete, copyStatus, copying, forceDataChanges, setBusy, showMessage, t.copyComplete, tt.downloading]","fix":{"range":[7378,7390],"text":"[copyComplete, copyStatus, copying, forceDataChanges, setBusy, showMessage, t.copyComplete, tt.downloading]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'getProjectDefault'. Either include it or remove the dependency array.","line":412,"column":5,"nodeType":"ArrayExpression","endLine":412,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [getProjectDefault, project]","fix":{"range":[12296,12305],"text":"[getProjectDefault, project]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'projectSections'. Either include it or remove the dependency array.","line":452,"column":5,"nodeType":"ArrayExpression","endLine":452,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [project, projectSections]","fix":{"range":[13578,13587],"text":"[project, projectSections]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\EditorSettings.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\ProjectAdvanced.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getOrgDefault' and 'personalTeam'. Either include them or remove the dependency array.","line":103,"column":6,"nodeType":"ArrayExpression","endLine":103,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, org, personalTeam]","fix":{"range":[3403,3408],"text":"[getOrgDefault, org, personalTeam]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'publishGroup', 'publishUser', 'setPublishAssigned', 'setSheetAssigned', 'sheetGroup', and 'sheetUser'. Either include them or remove the dependency array.","line":110,"column":6,"nodeType":"ArrayExpression","endLine":110,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [publishGroup, publishUser, setPublishAssigned, setSheetAssigned, sheetGroup, sheetUser]","fix":{"range":[3619,3621],"text":"[publishGroup, publishUser, setPublishAssigned, setSheetAssigned, sheetGroup, sheetUser]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setState', 'state.publishGroup', and 'state.publishUser'. Either include them or remove the dependency array.","line":125,"column":6,"nodeType":"ArrayExpression","endLine":125,"endColumn":62,"suggestions":[{"desc":"Update the dependencies array to be: [initialized, assignedPublishGroup, assignedPublishUser, state.publishGroup, state.publishUser, setState]","fix":{"range":[4051,4107],"text":"[initialized, assignedPublishGroup, assignedPublishUser, state.publishGroup, state.publishUser, setState]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setState', 'state.sheetGroup', and 'state.sheetUser'. Either include them or remove the dependency array.","line":139,"column":6,"nodeType":"ArrayExpression","endLine":139,"endColumn":58,"suggestions":[{"desc":"Update the dependencies array to be: [initialized, assignedSheetGroup, assignedSheetUser, state.sheetGroup, state.sheetUser, setState]","fix":{"range":[4481,4533],"text":"[initialized, assignedSheetGroup, assignedSheetUser, state.sheetGroup, state.sheetUser, setState]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\ProjectDescription.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\ProjectDialog.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'initState'. Either include it or remove the dependency array.","line":75,"column":6,"nodeType":"ArrayExpression","endLine":75,"endColumn":22,"suggestions":[{"desc":"Update the dependencies array to be: [initState, isOpen, values]","fix":{"range":[2439,2455],"text":"[initState, isOpen, values]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\ProjectName.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\ProjectSort.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'checkScriptureBooks', 'getOrgDefault', 'getProj', 'personalProjects', 'personalTeam', 'setOrgDefault', 'teamId', 'teamProjects', and 'updateSortKey'. Either include them or remove the dependency array.","line":128,"column":6,"nodeType":"ArrayExpression","endLine":128,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [checkScriptureBooks, getOrgDefault, getProj, personalProjects, personalTeam, setOrgDefault, teamId, teamProjects, updateSortKey]","fix":{"range":[4395,4397],"text":"[checkScriptureBooks, getOrgDefault, getProj, personalProjects, personalTeam, setOrgDefault, teamId, teamProjects, updateSortKey]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\ProjectStory.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\ProjectType.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\SortableItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\TableRow.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\projectDialogTypes.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectDialog\\projectSortUtils.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\ProjectMenu.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\SharedContentCreatorDialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\TeamActions.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\TeamDialog.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'defaultParams', 'getDefault', 'getOrgBible', 'memory?.cache', 'mode', 'processOptions.length', 'reset', and 't'. Either include them or remove the dependency array.","line":376,"column":6,"nodeType":"ArrayExpression","endLine":376,"endColumn":22,"suggestions":[{"desc":"Update the dependencies array to be: [values, isOpen, reset, mode, processOptions.length, defaultParams, getDefault, getOrgBible, memory?.cache, t]","fix":{"range":[11987,12003],"text":"[values, isOpen, reset, mode, processOptions.length, defaultParams, getDefault, getOrgBible, memory?.cache, t]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'bible', 'bibleName', 'description', 'getBible', 'isOpen', 'iso', 'owner', 'publishingData', and 'values?.team.id'. Either include them or remove the dependency array. You can also replace multiple useState variables with useReducer if 'setBible' needs the current value of 'bibleName'.","line":398,"column":6,"nodeType":"ArrayExpression","endLine":398,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [bible, bibleId, bibleName, description, getBible, isOpen, iso, owner, publishingData, values?.team.id]","fix":{"range":[12585,12594],"text":"[bible, bibleId, bibleName, description, getBible, isOpen, iso, owner, publishingData, values?.team.id]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getBibleOwner'. Either include it or remove the dependency array.","line":416,"column":6,"nodeType":"ArrayExpression","endLine":416,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [bible, getBibleOwner]","fix":{"range":[13341,13348],"text":"[bible, getBibleOwner]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\TeamItem.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'userIsOrgAdmin'. Either include it or remove the dependency array.","line":59,"column":62,"nodeType":"ArrayExpression","endLine":59,"endColumn":68,"suggestions":[{"desc":"Update the dependencies array to be: [team.id, userIsOrgAdmin]","fix":{"range":[2890,2896],"text":"[team.id, userIsOrgAdmin]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'teamProjects'. Either include it or remove the dependency array.","line":64,"column":5,"nodeType":"ArrayExpression","endLine":64,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [team.id, teamProjects]","fix":{"range":[3049,3055],"text":"[team.id, teamProjects]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\TeamPanel.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\TeamProjects.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\TeamSettings.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setOrg'. Either include it or remove the dependency array.","line":98,"column":6,"nodeType":"ArrayExpression","endLine":98,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [setOrg, team?.id]","fix":{"range":[2723,2733],"text":"[setOrg, team?.id]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\personalWorkflowOrg.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\personalWorkflowOrg.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\useCardSize.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\useCategoryGraphicEdit.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\useCategoryGraphicEdit.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Team\\useTeamActions.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TitleRecord.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'updateStackWidth'. Either include it or remove the dependency array. Mutable values like 'stackRef.current' aren't valid dependencies because mutating them doesn't re-render the component.","line":57,"column":6,"nodeType":"ArrayExpression","endLine":57,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [updateStackWidth]","fix":{"range":[1788,1806],"text":"[updateStackWidth]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TitleTabs.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'getTypeId'. Either include it or remove the dependency array.","line":89,"column":6,"nodeType":"ArrayExpression","endLine":89,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [getTypeId]","fix":{"range":[2707,2720],"text":"[getTypeId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearCompleted', 'clearRequested', 'handleSave', 'reset', 'saveCompleted', 'saveRequested', and 'toolId'. Either include them or remove the dependency array.","line":151,"column":6,"nodeType":"ArrayExpression","endLine":151,"endColumn":38,"suggestions":[{"desc":"Update the dependencies array to be: [toolsChanged, canSaveRecording, saveRequested, toolId, clearRequested, handleSave, saveCompleted, reset, clearCompleted]","fix":{"range":[4237,4269],"text":"[toolsChanged, canSaveRecording, saveRequested, toolId, clearRequested, handleSave, saveCompleted, reset, clearCompleted]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TitleUploader.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/immutability').","line":37,"column":5,"severity":1,"nodeType":null,"fix":{"range":[1042,1094],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { shallowEqual, useSelector } from 'react-redux';\nimport { IMediaTitleStrings } from '../model';\nimport { restoreScroll } from '../utils';\nimport { UploadType } from './UploadType';\nimport MediaUploadContent from './MediaUploadContent';\nimport { mediaTitleSelector } from '../selector';\n\ninterface IProps {\n defaultFilename?: string;\n isOpen: boolean;\n onOpen: (visible: boolean) => void;\n hasRights?: boolean; // required for upload\n finish?: (files: File[]) => void; // when conversion complete\n cancelled: React.RefObject;\n uploadType?: UploadType;\n uploadMethod: (files: File[]) => Promise;\n metadata?: React.JSX.Element;\n onSave?: () => void;\n onFiles?: (files: File[]) => void;\n}\n\nexport function TitleUploader(props: IProps) {\n const {\n isOpen,\n onOpen,\n cancelled,\n uploadType,\n hasRights,\n uploadMethod,\n metadata,\n onFiles,\n } = props;\n const t: IMediaTitleStrings = useSelector(mediaTitleSelector, shallowEqual);\n\n const uploadCancel = () => {\n onOpen(false);\n // eslint-disable-next-line react-hooks/immutability\n if (cancelled) cancelled.current = true;\n restoreScroll();\n };\n\n return isOpen ? (\n Boolean(hasRights)}\n uploadMethod={uploadMethod}\n cancelMethod={uploadCancel}\n metaData={metadata}\n saveText={t.upload}\n onFiles={onFiles}\n />\n ) : (\n <>\n );\n}\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TokenDialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TranscribeAddNote.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/immutability').","line":46,"column":7,"severity":1,"nodeType":null,"fix":{"range":[1286,1338],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { useState, useEffect } from 'react';\nimport {\n PassageD,\n ITranscribeAddNoteStrings,\n PassageStateChangeD,\n} from '../model';\nimport {\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n TextField,\n} from '@mui/material';\nimport { transcribeAddNoteSelector } from '../selector';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport { Button, commentProps } from '../control';\n\ninterface IProps {\n passageIn?: PassageD | undefined;\n pscIn?: PassageStateChangeD | undefined;\n visible: boolean;\n addMethod?: ((passageRec: PassageD) => void) | undefined;\n editMethod?: ((psc: PassageStateChangeD) => void) | undefined;\n cancelMethod?: (() => void) | undefined;\n}\n\nfunction TranscribeAddNote(props: IProps) {\n const { visible, addMethod, editMethod, cancelMethod, passageIn, pscIn } =\n props;\n const [open, setOpen] = useState(visible);\n const [comment, setComment] = useState('');\n const [inProcess, setInProcess] = useState(false);\n const t: ITranscribeAddNoteStrings = useSelector(\n transcribeAddNoteSelector,\n shallowEqual\n );\n\n const handleSave = () => {\n doAddOrSave();\n };\n const handleCommentChange = (e: any) => setComment(e.target.value);\n const doAddOrSave = async () => {\n setInProcess(true);\n\n if (pscIn) {\n // eslint-disable-next-line react-hooks/immutability\n pscIn.attributes.comments = comment;\n if (editMethod) editMethod(pscIn);\n } else if (comment !== '') {\n const passage = {\n ...passageIn,\n attributes: {\n ...passageIn?.attributes,\n lastComment: comment,\n },\n } as PassageD;\n if (addMethod) {\n addMethod(passage);\n }\n }\n\n setOpen(false);\n setInProcess(false);\n };\n const handleCancel = () => {\n setComment('');\n if (cancelMethod) {\n cancelMethod();\n }\n setOpen(false);\n };\n\n useEffect(() => {\n setOpen(visible);\n setComment(pscIn?.attributes.comments || '');\n }, [visible, pscIn]);\n\n return (\n
\n \n {t.addNoteTitle}\n \n \n \n \n \n {t.cancel}\n \n \n {t.save}\n \n \n \n
\n );\n}\n\nexport default TranscribeAddNote;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TranscribeReject.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":81,"column":5,"severity":1,"nodeType":null,"fix":{"range":[2220,2278],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import React, { useState, useEffect } from 'react';\nimport {\n ITranscribeRejectStrings,\n ActivityStates,\n MediaFile,\n ITranscriberStrings,\n} from '../model';\nimport {\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n FormControl,\n FormLabel,\n FormControlLabel,\n RadioGroup,\n Radio,\n TextField,\n} from '@mui/material';\nimport { Button, commentProps } from '../control';\nimport { transcribeRejectSelector, transcriberSelector } from '../selector';\nimport { shallowEqual, useSelector } from 'react-redux';\n\ninterface IProps {\n mediaIn: MediaFile;\n visible: boolean;\n editMethod?: (mediaRec: MediaFile, comment: string) => void;\n cancelMethod?: () => void;\n}\n\nfunction TranscribeReject(props: IProps) {\n const { visible, editMethod, cancelMethod, mediaIn } = props;\n const [open, setOpen] = useState(visible);\n const [next, setNext] = useState();\n const [comment, setComment] = useState('');\n const [inProcess, setInProcess] = useState(false);\n const tr: ITranscribeRejectStrings = useSelector(\n transcribeRejectSelector,\n shallowEqual\n );\n const t: ITranscriberStrings = useSelector(transcriberSelector, shallowEqual);\n\n const handleSave = () => {\n doAddOrSave();\n };\n const handleChange = (event: React.ChangeEvent) => {\n setNext((event.target as HTMLInputElement).value as ActivityStates);\n };\n const handleCommentChange = (e: any) => setComment(e.target.value);\n const doAddOrSave = async () => {\n setInProcess(true);\n if (next !== mediaIn.attributes.transcriptionstate || comment !== '') {\n const mediafile = {\n ...mediaIn,\n attributes: {\n ...mediaIn.attributes,\n transcriptionstate: next,\n },\n } as MediaFile;\n if (editMethod) {\n editMethod(mediafile, comment);\n }\n }\n setOpen(false);\n setInProcess(false);\n };\n const handleCancel = () => {\n if (cancelMethod) {\n cancelMethod();\n }\n setOpen(false);\n };\n\n useEffect(() => {\n setNext(\n mediaIn?.attributes?.transcriptionstate === ActivityStates.Transcribing\n ? ActivityStates.NeedsNewRecording\n : ActivityStates.NeedsNewTranscription\n );\n setComment('');\n /* eslint-disable-next-line react-hooks/exhaustive-deps */\n }, [mediaIn]);\n\n useEffect(() => {\n setOpen(visible);\n }, [visible]);\n\n return (\n
\n \n {tr.rejectTitle}\n \n \n {tr.rejectReason}\n \n }\n label={tr.needsAudio}\n />\n }\n label={tr.needsCorrection}\n />\n }\n label={tr.incomplete}\n />\n \n \n \n \n \n \n {tr.cancel}\n \n \n {t.reject}\n \n \n \n
\n );\n}\n\nexport default TranscribeReject;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Transcriber.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getOrgDefault' and 'transcribeDefaultParams'. Either include them or remove the dependency array.","line":456,"column":6,"nodeType":"ArrayExpression","endLine":456,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, organization, transcribeDefaultParams]","fix":{"range":[14539,14553],"text":"[getOrgDefault, organization, transcribeDefaultParams]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getOrgDefault'. Either include it or remove the dependency array.","line":463,"column":6,"nodeType":"ArrayExpression","endLine":463,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, organization]","fix":{"range":[14739,14753],"text":"[getOrgDefault, organization]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'textAreaStyle'. Either include it or remove the dependency array. You can also do a functional update 'setTextAreaStyle(t => ...)' if you only need 'textAreaStyle' in the 'setTextAreaStyle' call.","line":485,"column":6,"nodeType":"ArrayExpression","endLine":485,"endColumn":44,"suggestions":[{"desc":"Update the dependencies array to be: [pdBusy, loading, boxHeight, projData, textAreaStyle]","fix":{"range":[15447,15485],"text":"[pdBusy, loading, boxHeight, projData, textAreaStyle]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'artifactTypeSlug', 'integrations', 'keys', 'offlineOnly', 'subscribe', and 'unsubscribe'. Either include them or remove the dependency array.","line":518,"column":6,"nodeType":"ArrayExpression","endLine":518,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [artifactTypeSlug, integrations, keys, offlineOnly, subscribe, unsubscribe]","fix":{"range":[16403,16405],"text":"[artifactTypeSlug, integrations, keys, offlineOnly, subscribe, unsubscribe]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'keys' and 'subscribe'. Either include them or remove the dependency array.","line":525,"column":6,"nodeType":"ArrayExpression","endLine":525,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [allDone, keys, subscribe]","fix":{"range":[16571,16580],"text":"[allDone, keys, subscribe]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'artifactTypeSlug' and 'offlineOnly'. Either include them or remove the dependency array.","line":550,"column":6,"nodeType":"ArrayExpression","endLine":550,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [artifactTypeSlug, integrations, offlineOnly]","fix":{"range":[17294,17308],"text":"[artifactTypeSlug, integrations, offlineOnly]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'changed', 'clearCompleted', 'clearRequested', 'handleSave', 'isChanged', and 'saveRequested'. Either include them or remove the dependency array.","line":561,"column":6,"nodeType":"ArrayExpression","endLine":561,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [changed, clearCompleted, clearRequested, handleSave, isChanged, saveRequested, toolsChanged]","fix":{"range":[17628,17642],"text":"[changed, clearCompleted, clearRequested, handleSave, isChanged, saveRequested, toolsChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'boxHeight'. Either include it or remove the dependency array.","line":573,"column":6,"nodeType":"ArrayExpression","endLine":573,"endColumn":49,"suggestions":[{"desc":"Update the dependencies array to be: [discussionSize, chooserSize, defaultWidth, boxHeight]","fix":{"range":[18034,18077],"text":"[discussionSize, chooserSize, defaultWidth, boxHeight]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setTransSelected' and 'transSelected'. Either include them or remove the dependency array.","line":581,"column":6,"nodeType":"ArrayExpression","endLine":581,"endColumn":23,"suggestions":[{"desc":"Update the dependencies array to be: [playerMediafile, setTransSelected, transSelected]","fix":{"range":[18383,18400],"text":"[playerMediafile, setTransSelected, transSelected]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getTranscription', 'playerMediafile?.id', 'setSelected', and 'showTranscription'. Either include them or remove the dependency array.","line":606,"column":6,"nodeType":"ArrayExpression","endLine":606,"endColumn":29,"suggestions":[{"desc":"Update the dependencies array to be: [getTranscription, hasRow, playerMediafile?.id, setSelected, showTranscription, transSelected]","fix":{"range":[19228,19251],"text":"[getTranscription, hasRow, playerMediafile?.id, setSelected, showTranscription, transSelected]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getTranscription', 'playerMediafile?.id', and 'setSelected'. Either include them or remove the dependency array.","line":658,"column":6,"nodeType":"ArrayExpression","endLine":658,"endColumn":17,"suggestions":[{"desc":"Update the dependencies array to be: [getTranscription, mediafile, playerMediafile?.id, setSelected]","fix":{"range":[21110,21121],"text":"[getTranscription, mediafile, playerMediafile?.id, setSelected]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'launchTimer'. Either include it or remove the dependency array.","line":675,"column":6,"nodeType":"ArrayExpression","endLine":675,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [launchTimer, passage]","fix":{"range":[21595,21604],"text":"[launchTimer, passage]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getOrganizedBy', 'mediafile?.attributes.transcriptionstate', 'resetParatextText', 'save', 'sharedStr', 'showMessage', 'showTranscription', 't.pullParatextStatus', and 'toolChanged'. Either include them or remove the dependency array.","line":705,"column":6,"nodeType":"ArrayExpression","endLine":705,"endColumn":27,"suggestions":[{"desc":"Update the dependencies array to be: [getOrganizedBy, mediafile?.attributes.transcriptionstate, paratext_textStatus, resetParatextText, save, sharedStr, showMessage, showTranscription, t.pullParatextStatus, toolChanged]","fix":{"range":[22464,22485],"text":"[getOrganizedBy, mediafile?.attributes.transcriptionstate, paratext_textStatus, resetParatextText, save, sharedStr, showMessage, showTranscription, t.pullParatextStatus, toolChanged]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getProjType', 'memory', and 'noParatext'. Either include them or remove the dependency array.","line":789,"column":6,"nodeType":"ArrayExpression","endLine":797,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [project, projType, artifactTypeSlug, artifactId, offline, stepSettings, availSpellLangs, memory, getProjType, noParatext]","fix":{"range":[25344,25466],"text":"[project, projType, artifactTypeSlug, artifactId, offline, stepSettings, availSpellLangs, memory, getProjType, noParatext]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'assigned'. Either include it or remove the dependency array.","line":805,"column":6,"nodeType":"ArrayExpression","endLine":805,"endColumn":31,"suggestions":[{"desc":"Update the dependencies array to be: [assigned, selectedMediaRow, state]","fix":{"range":[25734,25759],"text":"[assigned, selectedMediaRow, state]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'accessToken', 'errorReporter', and 'getUserName'. Either include them or remove the dependency array.","line":815,"column":6,"nodeType":"ArrayExpression","endLine":815,"endColumn":71,"suggestions":[{"desc":"Update the dependencies array to be: [paratext_username, paratext_usernameStatus, noParatext, offline, getUserName, accessToken, errorReporter]","fix":{"range":[26080,26145],"text":"[paratext_username, paratext_usernameStatus, noParatext, offline, getUserName, accessToken, errorReporter]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":895,"column":5,"nodeType":"ArrayExpression","endLine":895,"endColumn":33,"suggestions":[{"desc":"Update the dependencies array to be: [memory, passage.id, user, onReject]","fix":{"range":[28195,28223],"text":"[memory, passage.id, user, onReject]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":917,"column":5,"nodeType":"ArrayExpression","endLine":917,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [memory, user]","fix":{"range":[28767,28773],"text":"[memory, user]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'onReloadPlayer' and 'save'. Either include them or remove the dependency array.","line":948,"column":5,"nodeType":"ArrayExpression","endLine":948,"endColumn":65,"suggestions":[{"desc":"Update the dependencies array to be: [state, hasChecking, noParatext, save, onReloadPlayer, setComplete, errorReporter]","fix":{"range":[29654,29714],"text":"[state, hasChecking, noParatext, save, onReloadPlayer, setComplete, errorReporter]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'memory' and 'stateRole'. Either include them or remove the dependency array.","line":979,"column":5,"nodeType":"ArrayExpression","endLine":979,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [memory, section, stateRole, user]","fix":{"range":[30541,30556],"text":"[memory, section, stateRole, user]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'projData'. Either include it or remove the dependency array.","line":1008,"column":6,"nodeType":"ArrayExpression","endLine":1008,"endColumn":33,"suggestions":[{"desc":"Update the dependencies array to be: [settingsState, artifactId, projData]","fix":{"range":[31303,31330],"text":"[settingsState, artifactId, projData]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'contentVerses'. Either include it or remove the dependency array.","line":1175,"column":6,"nodeType":"ArrayExpression","endLine":1175,"endColumn":47,"suggestions":[{"desc":"Update the dependencies array to be: [textValue, verseLabels, playerMediafile, contentVerses]","fix":{"range":[36502,36543],"text":"[textValue, verseLabels, playerMediafile, contentVerses]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has an unnecessary dependency: 'orgSteps'. Either exclude it or remove the dependency array.","line":1267,"column":5,"nodeType":"ArrayExpression","endLine":1267,"endColumn":31,"suggestions":[{"desc":"Update the dependencies array to be: [getAsrSettings]","fix":{"range":[39376,39402],"text":"[getAsrSettings]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'getName' and 'tPlayer.recognizeSpeech'. Either include them or remove the dependency array.","line":1281,"column":6,"nodeType":"ArrayExpression","endLine":1281,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [asrSettings?.language.bcp47, asrSettings?.language?.languageName, getName, tPlayer.recognizeSpeech]","fix":{"range":[39794,39807],"text":"[asrSettings?.language.bcp47, asrSettings?.language?.languageName, getName, tPlayer.recognizeSpeech]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TranscriptionShow.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getTranscription', 'memory', 'org', 'projectId', and 'workflowSteps'. Either include them or remove the dependency array.","line":125,"column":6,"nodeType":"ArrayExpression","endLine":125,"endColumn":31,"suggestions":[{"desc":"Update the dependencies array to be: [id, isMediaId, exportId, memory, getTranscription, projectId, workflowSteps, org]","fix":{"range":[4251,4276],"text":"[id, isMediaId, exportId, memory, getTranscription, projectId, workflowSteps, org]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TranscriptionTab.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'artifactLabel'. Either include it or remove the dependency array.","line":242,"column":5,"nodeType":"ArrayExpression","endLine":242,"endColumn":31,"suggestions":[{"desc":"Update the dependencies array to be: [artifactLabel, artifactType]","fix":{"range":[8534,8560],"text":"[artifactLabel, artifactType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'getTypeId'. Either include it or remove the dependency array.","line":326,"column":5,"nodeType":"ArrayExpression","endLine":326,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [artifactType, getTypeId]","fix":{"range":[10900,10914],"text":"[artifactType, getTypeId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'exportComplete', 'setBusy', 'showTitledMessage', 't.downloading', and 't.exportProject'. Either include them or remove the dependency array.","line":478,"column":6,"nodeType":"ArrayExpression","endLine":478,"endColumn":43,"suggestions":[{"desc":"Update the dependencies array to be: [exportUrl, exportName, exportAnchor, showTitledMessage, t.exportProject, t.downloading, exportComplete, setBusy]","fix":{"range":[15342,15379],"text":"[exportUrl, exportName, exportAnchor, showTitledMessage, t.exportProject, t.downloading, exportComplete, setBusy]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'enableOffsite', 'exportComplete', 'exportFile', 'exportName', 'setBusy', 'setEnableOffsite', 'showMessage', 'showTitledMessage', 't.error', and 'translateError'. Either include them or remove the dependency array.","line":502,"column":6,"nodeType":"ArrayExpression","endLine":502,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [enableOffsite, exportComplete, exportFile, exportName, exportStatus, setBusy, setEnableOffsite, showMessage, showTitledMessage, t.error, translateError]","fix":{"range":[16104,16118],"text":"[enableOffsite, exportComplete, exportFile, exportName, exportStatus, setBusy, setEnableOffsite, showMessage, showTitledMessage, t.error, translateError]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getPlanType' and 'setPlan'. Either include them or remove the dependency array.","line":515,"column":6,"nodeType":"ArrayExpression","endLine":515,"endColumn":25,"suggestions":[{"desc":"Update the dependencies array to be: [projectPlan, plan, setPlan, getPlanType]","fix":{"range":[16485,16504],"text":"[projectPlan, plan, setPlan, getPlanType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getAssignments'. Either include it or remove the dependency array.","line":606,"column":6,"nodeType":"ArrayExpression","endLine":616,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [plan, projectPlans, passages, sections, users, roles, activityState, allBookData, openSections, getAssignments]","fix":{"range":[19530,19667],"text":"[plan, projectPlans, passages, sections, users, roles, activityState, allBookData, openSections, getAssignments]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'handleEaf', 't.plan', 't.sectionstate', 't.updated', and 'ts.passages'. Either include them or remove the dependency array.","line":650,"column":5,"nodeType":"ArrayExpression","endLine":650,"endColumn":31,"suggestions":[{"desc":"Update the dependencies array to be: [getOrganizedBy, addWidth, t.sectionstate, t.plan, t.updated, ts.passages, handleEaf]","fix":{"range":[20638,20664],"text":"[getOrganizedBy, addWidth, t.sectionstate, t.plan, t.updated, ts.passages, handleEaf]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'columnVisibilityModel'. Either include it or remove the dependency array.","line":663,"column":5,"nodeType":"ArrayExpression","endLine":663,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [columnVisibilityModel, columns]","fix":{"range":[21008,21017],"text":"[columnVisibilityModel, columns]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setDimensions'. Either include it or remove the dependency array.","line":677,"column":6,"nodeType":"ArrayExpression","endLine":677,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [setDimensions, totalWidth]","fix":{"range":[21363,21375],"text":"[setDimensions, totalWidth]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setDimensions'. Either include it or remove the dependency array.","line":691,"column":6,"nodeType":"ArrayExpression","endLine":691,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [setDimensions]","fix":{"range":[21729,21731],"text":"[setDimensions]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TranscriptionViewCell.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\TreeDataGrid.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\UploadType.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Uploader.test.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":1,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":1,"endColumn":13}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import React from 'react';\nimport { act, cleanup, render } from '@testing-library/react';\nimport { UploadType } from './UploadType';\n\ntype PassageRecordDlgProps = {\n afterUploadCb: (mediaId: string | undefined) => Promise;\n beforeUpload?: () => Promise;\n};\n\nlet capturedDlg: PassageRecordDlgProps | undefined;\n\njest.mock('./PassageRecordDlg', () => ({\n __esModule: true,\n default: (props: PassageRecordDlgProps) => {\n capturedDlg = props;\n return
;\n },\n}));\n\njest.mock('./MediaUpload', () => ({\n __esModule: true,\n default: () => null,\n FaithbridgeType: 'audio/mpeg/s3link',\n}));\n\njest.mock('../store', () => ({\n uploadFiles: jest.fn(() => ({ type: 'UPLOAD_LIST' })),\n nextUpload: jest.fn(() => ({ type: 'NEXT_UPLOAD' })),\n uploadComplete: jest.fn(() => ({ type: 'UPLOAD_COMPLETE' })),\n}));\n\njest.mock('../selector', () => ({\n mediaTabSelector: () => ({\n uploadComplete: '{0} of {1} files uploaded successfully.',\n unsupported: '{0}',\n toobig: '{0} {1} {2}',\n selectFiles: 'Select files',\n }),\n sharedSelector: () => ({\n mediaAttached: 'Media attached',\n }),\n}));\n\njest.mock('react-redux', () => ({\n shallowEqual: jest.fn(),\n useDispatch: () => jest.fn((action: unknown) => action),\n useSelector: (sel: (state: { upload: { errmsg: string } }) => unknown) =>\n sel({ upload: { errmsg: '' } }),\n}));\n\njest.mock('../context/TokenProvider', () => {\n const ReactActual = jest.requireActual('react');\n return {\n TokenContext: ReactActual.createContext({\n state: { accessToken: 'tok' },\n }),\n };\n});\n\nconst mockMemory = { cache: { query: jest.fn(() => []) }, keyMap: {} };\nconst mockCoordinator = {\n getSource: jest.fn((name: string) => {\n if (name === 'memory') return mockMemory;\n return {};\n }),\n};\n\njest.mock('../context/useGlobal', () => ({\n useGlobal: jest.fn((key: string) => {\n const mockValues: Record = {\n developer: false,\n coordinator: mockCoordinator,\n errorReporter: {},\n orbitRetries: 0,\n importexportBusy: false,\n plan: '',\n user: 'user-1',\n progress: 0,\n };\n return [mockValues[key], jest.fn()];\n }),\n useGetGlobal: jest.fn(() => (key: string) => {\n if (key === 'offline') return false;\n if (key === 'importexportBusy') return false;\n return undefined;\n }),\n}));\n\njest.mock('../crud', () => ({\n findRecord: jest.fn(),\n pullTableList: jest.fn(),\n related: jest.fn(),\n remoteIdNum: jest.fn((_table: string, id: string) => id),\n useArtifactType: () => ({\n localizedArtifactTypeFromId: jest.fn(() => 'artifact-label'),\n }),\n useOfflnMediafileCreate: () => ({\n createMedia: jest.fn(),\n }),\n VernacularTag: null,\n}));\n\njest.mock('../utils', () => ({\n restoreScroll: jest.fn(),\n}));\n\njest.mock('../utils/passageDefaultFilename', () => ({\n passageDefaultSuffix: jest.fn(() => ''),\n}));\n\njest.mock('../utils/typeLimit', () => ({\n typeLimit: jest.fn(() => 100),\n}));\n\njest.mock('../utils/contentType', () => ({\n getContentType: jest.fn(() => 'audio/webm'),\n}));\n\njest.mock('../store/upload/uploadTerminalMessages', () => ({\n formatUploadTerminalFailureMessage: jest.fn(() => 'upload failed'),\n}));\n\nimport Uploader from './Uploader';\n\nfunction renderUploader(beforeUpload: () => Promise) {\n const cancelled = { current: false };\n return render(\n \n );\n}\n\ndescribe('Uploader recorded path beforeUpload', () => {\n beforeEach(() => {\n capturedDlg = undefined;\n jest.useFakeTimers();\n });\n\n afterEach(() => {\n act(() => {\n jest.runOnlyPendingTimers();\n });\n jest.useRealTimers();\n cleanup();\n });\n\n /**\n * Recorded save goes MediaRecord → useMediaUpload (await beforeUpload, then\n * stage) → Uploader.afterUploadCb on success. Copilot r3919030521: the\n * after-upload hook must not commit again — SelectArtifactCategory.commit()\n * is not idempotent if React has not re-rendered the new category yet.\n */\n it('commits deferred metadata once when a recording upload succeeds', async () => {\n const created: string[] = [];\n const beforeUpload = jest.fn(async () => {\n created.push(`cat-${created.length + 1}`);\n });\n renderUploader(beforeUpload);\n expect(capturedDlg?.beforeUpload).toBe(beforeUpload);\n\n await act(async () => {\n await capturedDlg!.beforeUpload!();\n await capturedDlg!.afterUploadCb('media-1');\n });\n\n expect(created).toEqual(['cat-1']);\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\Uploader.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'clearErrors'. Either include it or remove the dependency array.","line":186,"column":6,"nodeType":"ArrayExpression","endLine":186,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [clearErrors, isOpen]","fix":{"range":[7460,7468],"text":"[clearErrors, isOpen]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'errMsgs', 'setBusy', 't.toobig', 't.unsupported', and 'uploadType'. Either include them or remove the dependency array.","line":513,"column":6,"nodeType":"ArrayExpression","endLine":513,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [errMsgs, setBusy, t.toobig, t.unsupported, uploadError, uploadType]","fix":{"range":[17984,17997],"text":"[errMsgs, setBusy, t.toobig, t.unsupported, uploadError, uploadType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'uploadMedia'. Either include it or remove the dependency array.","line":520,"column":6,"nodeType":"ArrayExpression","endLine":520,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [importList, uploadMedia]","fix":{"range":[18170,18182],"text":"[importList, uploadMedia]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\UserActionCell.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\UserActionCell.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\UserAdd.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\UserAvatar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\UserMenu.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":110,"column":5,"severity":1,"nodeType":null,"fix":{"range":[3421,3476],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import React, { useEffect } from 'react';\nimport { useGlobal } from '../context/useGlobal';\nimport { IMainStrings, ISharedStrings, User, UserD } from '../model';\nimport {\n IconButton,\n ListItemIcon,\n ListItemText,\n Typography,\n Divider,\n styled,\n MenuItemProps,\n Checkbox,\n} from '@mui/material';\nimport ExitIcon from '@mui/icons-material/ExitToApp';\nimport AccountIcon from '@mui/icons-material/AccountCircle';\nimport ClearIcon from '@mui/icons-material/Clear';\nimport { StyledMenu, StyledMenuItem } from '../control/StyledMenu';\nimport UserAvatar from './UserAvatar';\nimport { isElectron } from '../../api-variable';\nimport {\n localizeRole,\n restoreScroll,\n LocalKey,\n localUserKey,\n useMobile,\n} from '../utils';\nimport { useOrbitData } from '../hoc/useOrbitData';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport { mainSelector, sharedSelector } from '../selector';\nimport ProfileDialog from './ProfileDialog';\nimport { useRole } from '../crud/useRole';\nimport { useOrganizedBy } from '../crud';\nimport {\n useTeamWorkflowProcess,\n BOLD_WORKFLOW_PROCESS,\n} from '../crud/useTeamWorkflowProcess';\nimport { useRenderProfiler, useWhyRender } from '../utils/perf';\n\nconst TermsItem = styled(StyledMenuItem)(() => ({\n textAlign: 'center',\n lineHeight: 1,\n paddingBottom: 0,\n '& .MuiListItemText-primary': {\n fontSize: 'small',\n },\n}));\n\nconst roleStyle = {\n display: 'flex',\n flexDirection: 'column',\n} as React.CSSProperties;\n\ninterface IProps {\n action: (what: string) => void;\n}\n\nexport function UserMenu(props: IProps) {\n useRenderProfiler('UserMenu');\n const { action } = props;\n const users = useOrbitData('user');\n const [orgRole] = useGlobal('orgRole'); //verified this is not used in a function 2/18/25\n const [developer] = useGlobal('developer');\n const [user] = useGlobal('user');\n const [, setMobileView] = useGlobal('mobileView');\n const [org] = useGlobal('organization');\n const [addStoryOrPassage, setAddStoryOrPassage] =\n useGlobal('addStoryOrPassage');\n const [isDeveloper] = useGlobal('developer');\n const { userIsAdmin } = useRole();\n const { getOrganizedBy } = useOrganizedBy();\n const isBoldWorkflow = useTeamWorkflowProcess(org) === BOLD_WORKFLOW_PROCESS;\n const [anchorEl, setAnchorEl] = React.useState(null);\n const [shift, setShift] = React.useState(false);\n const [userRec, setUserRec] = React.useState(undefined);\n const [profileOpen, setProfileOpen] = React.useState(false);\n const { isMobileView, isMobileWidth } = useMobile();\n const t: IMainStrings = useSelector(mainSelector, shallowEqual);\n const ts: ISharedStrings = useSelector(sharedSelector, shallowEqual);\n useWhyRender('UserMenu', {\n users,\n user,\n org,\n orgRole,\n isBoldWorkflow,\n userIsAdmin,\n addStoryOrPassage,\n anchorEl,\n userRec,\n t,\n ts,\n });\n\n const handleClick = (event: React.MouseEvent) => {\n setShift(event.shiftKey);\n setAnchorEl(event.currentTarget);\n };\n\n const handleProfile = (visible: boolean) => () => {\n if (visible !== profileOpen) setProfileOpen(visible);\n restoreScroll();\n setAnchorEl(null);\n };\n\n useEffect(() => {\n const userRecs = users.filter((u) => u.id === user) as UserD[];\n const newRec = userRecs.length > 0 ? userRecs[0] : undefined;\n if (userRec !== newRec) {\n setUserRec(newRec);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [user, users, userRec]);\n\n const handleAction = (what: string) => () => {\n setAnchorEl(null);\n if (action) action(what);\n };\n\n const handleMobileViewToggle = () => {\n const newValue = !isMobileView;\n setMobileView(newValue);\n localStorage.setItem(localUserKey(LocalKey.mobileView), String(newValue));\n setAnchorEl(null);\n };\n\n const handleAddStoryOrPassageToggle = () => {\n // session-only flag; intentionally not persisted to localStorage\n setAddStoryOrPassage(!addStoryOrPassage);\n setAnchorEl(null);\n };\n\n return (\n
\n \n \n \n \n {orgRole && (\n \n \n \n {`${t.orgRole} ${localizeRole(orgRole, ts)}`}\n \n
\n }\n />\n \n )}\n \n \n \n \n \n \n {!isMobileWidth && isDeveloper && (\n \n \n \n \n \n \n )}\n {isBoldWorkflow && !userIsAdmin && (\n \n \n \n \n \n \n )}\n {shift && !isElectron && (\n \n \n \n \n \n \n )}\n {shift && (\n \n \n \n \n \n \n )}\n {shift && developer && (\n \n \n \n \n \n \n )}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n
\n );\n}\n\nexport default UserMenu;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\UserTable.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 't.addMember' and 'ts'. Either include them or remove the dependency array.","line":198,"column":6,"nodeType":"ArrayExpression","endLine":198,"endColumn":59,"suggestions":[{"desc":"Update the dependencies array to be: [organization, users, roles, organizationMemberships, t.addMember, ts]","fix":{"range":[6282,6335],"text":"[organization, users, roles, organizationMemberships, t.addMember, ts]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\WSAudioPlayer.hotkeys.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\WSAudioPlayer.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'loadRegions'. Either include it or remove the dependency array.","line":994,"column":6,"nodeType":"ArrayExpression","endLine":1000,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [notifySegmentInteraction, onClearSegments, wsClearRegions, verses, loadRegions, onSegmentChange]","fix":{"range":[32485,32594],"text":"[notifySegmentInteraction, onClearSegments, wsClearRegions, verses, loadRegions, onSegmentChange]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'unsubscribe' and 'warnMicrophoneDisconnected'. Either include them or remove the dependency array.","line":1080,"column":6,"nodeType":"ArrayExpression","endLine":1080,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [unsubscribe, warnMicrophoneDisconnected]","fix":{"range":[34748,34750],"text":"[unsubscribe, warnMicrophoneDisconnected]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getOrgDefault' and 'handleRefresh'. Either include them or remove the dependency array.","line":1088,"column":6,"nodeType":"ArrayExpression","endLine":1088,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, handleRefresh, org]","fix":{"range":[34950,34955],"text":"[getOrgDefault, handleRefresh, org]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'launchTimer'. Either include it or remove the dependency array.","line":1115,"column":6,"nodeType":"ArrayExpression","endLine":1115,"endColumn":17,"suggestions":[{"desc":"Update the dependencies array to be: [autoStart, launchTimer]","fix":{"range":[35573,35584],"text":"[autoStart, launchTimer]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'wsSetHeight'. Either include it or remove the dependency array.","line":1122,"column":6,"nodeType":"ArrayExpression","endLine":1122,"endColumn":54,"suggestions":[{"desc":"Update the dependencies array to be: [height, waitingForAI, keepItSmall, hideToolbar, wsSetHeight]","fix":{"range":[35805,35853],"text":"[height, waitingForAI, keepItSmall, hideToolbar, wsSetHeight]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setInitialPosition' and 'wsGoto'. Either include them or remove the dependency array.","line":1131,"column":6,"nodeType":"ArrayExpression","endLine":1131,"endColumn":30,"suggestions":[{"desc":"Update the dependencies array to be: [initialposition, ready, setInitialPosition, wsGoto]","fix":{"range":[36142,36166],"text":"[initialposition, ready, setInitialPosition, wsGoto]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'wsAddMarkers'. Either include it or remove the dependency array.","line":1139,"column":6,"nodeType":"ArrayExpression","endLine":1139,"endColumn":32,"suggestions":[{"desc":"Update the dependencies array to be: [markers, duration, ready, wsAddMarkers]","fix":{"range":[36404,36430],"text":"[markers, duration, ready, wsAddMarkers]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'loadRegions' and 'wsGetRegions'. Either include them or remove the dependency array.","line":1149,"column":6,"nodeType":"ArrayExpression","endLine":1149,"endColumn":23,"suggestions":[{"desc":"Update the dependencies array to be: [segments, ready, wsGetRegions, loadRegions]","fix":{"range":[36704,36721],"text":"[segments, ready, wsGetRegions, loadRegions]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useLayoutEffect has a missing dependency: 'setReady'. Either include it or remove the dependency array.","line":1175,"column":6,"nodeType":"ArrayExpression","endLine":1175,"endColumn":26,"suggestions":[{"desc":"Update the dependencies array to be: [blob, setBlobReady, setReady]","fix":{"range":[37644,37664],"text":"[blob, setBlobReady, setReady]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setBusy', 'setDuration', 'setProgress', 'setReady', 'wsClear', 'wsLoad', and 'wsPause'. Either include them or remove the dependency array.","line":1195,"column":6,"nodeType":"ArrayExpression","endLine":1195,"endColumn":21,"suggestions":[{"desc":"Update the dependencies array to be: [blob, doReset, setBusy, setDuration, setProgress, setReady, wsClear, wsLoad, wsPause]","fix":{"range":[38149,38164],"text":"[blob, doReset, setBusy, setDuration, setProgress, setReady, wsClear, wsLoad, wsPause]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'wsSetPlaybackRate'. Either include it or remove the dependency array.","line":1200,"column":6,"nodeType":"ArrayExpression","endLine":1200,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [playbackRate, wsSetPlaybackRate]","fix":{"range":[38310,38324],"text":"[playbackRate, wsSetPlaybackRate]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'handlePlayStatus'. Either include it or remove the dependency array.","line":1345,"column":6,"nodeType":"ArrayExpression","endLine":1345,"endColumn":36,"suggestions":[{"desc":"Update the dependencies array to be: [isPlaying, request, duration, handlePlayStatus]","fix":{"range":[42374,42404],"text":"[isPlaying, request, duration, handlePlayStatus]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'renderRecordButton'. Either include it or remove the dependency array.","line":2286,"column":5,"nodeType":"ArrayExpression","endLine":2301,"endColumn":6,"suggestions":[{"desc":"Update the dependencies array to be: [allowRecord, recording, showDockedRecordButton, renderRecordButton]","fix":{"range":[70455,70748],"text":"[allowRecord, recording, showDockedRecordButton, renderRecordButton]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\WSAudioPlayerRate.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":71,"column":7,"severity":1,"nodeType":null,"fix":{"range":[2322,2377],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'handleFaster', 'handleSlower', 'subscribe', and 'unsubscribe'. Either include them or remove the dependency array.","line":75,"column":6,"nodeType":"ArrayExpression","endLine":75,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [handleFaster, handleSlower, subscribe, unsubscribe]","fix":{"range":[2497,2499],"text":"[handleFaster, handleSlower, subscribe, unsubscribe]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import React, { useContext, useEffect, useRef } from 'react';\nimport { Grid, Box, IconButton, SxProps } from '@mui/material';\nimport { FaAngleDoubleUp, FaAngleDoubleDown } from 'react-icons/fa';\nimport type { IconBaseProps } from 'react-icons/lib';\nimport { IosSlider } from '../control/IosSlider';\nimport { LightTooltip } from '../control/LightTooltip';\nimport { IWsAudioPlayerStrings } from '../model';\nimport { useSelector } from 'react-redux';\nimport { wsAudioPlayerSelector } from '../selector';\nimport { shallowEqual } from 'react-redux';\nimport { HotKeyContext } from '../context/HotKeyContext';\n\nconst AngleDoubleUp = FaAngleDoubleUp as unknown as React.FC;\nconst AngleDoubleDown = FaAngleDoubleDown as unknown as React.FC;\n\nconst toolbarProp = {\n flexDirection: 'row',\n alignItems: 'center',\n justifyItems: 'flex-start',\n display: 'flex',\n} as SxProps;\n\nconst MIN_SPEED = 0.25;\nconst MAX_SPEED = 4;\nconst SLOWER_KEY = 'F4,CTRL+4';\nconst FASTER_KEY = 'F5,CTRL+5';\n\ninterface IProps {\n playbackRate: number;\n setPlaybackRate: (rate: number) => void;\n recording: boolean;\n}\n\nfunction WSAudioPlayerRate(props: IProps) {\n const { playbackRate, setPlaybackRate, recording } = props;\n const playbackRateRef = useRef(playbackRate);\n const { subscribe, unsubscribe, localizeHotKey } =\n useContext(HotKeyContext).state;\n const t: IWsAudioPlayerStrings = useSelector(\n wsAudioPlayerSelector,\n shallowEqual\n );\n\n useEffect(() => {\n playbackRateRef.current = playbackRate;\n }, [playbackRate]);\n\n const handleSliderChange = (event: Event, value: number | number[]) => {\n if (Array.isArray(value)) value = value[0]; //won't be\n setPlaybackRate(value);\n };\n\n const handleFaster = () => {\n if (playbackRateRef.current === MAX_SPEED || recording) return false;\n setPlaybackRate(Math.min(MAX_SPEED, playbackRateRef.current * 2));\n return true;\n };\n\n const handleSlower = () => {\n if (playbackRateRef.current === MIN_SPEED || recording) return false;\n setPlaybackRate(Math.max(MIN_SPEED, playbackRateRef.current / 2));\n return true;\n };\n useEffect(() => {\n const keys = [\n { key: SLOWER_KEY, cb: handleSlower },\n { key: FASTER_KEY, cb: handleFaster },\n ];\n keys.forEach((k) => subscribe(k.key, k.cb));\n return () => {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n keys.forEach((k) => unsubscribe(k.key));\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n return (\n <>\n \n \n <>\n \n \n \n {' '}\n \n \n \n `${value}x`}\n valueLabelFormat={(value) => `${value}x`}\n onChange={handleSliderChange}\n />\n \n \n \n {' '}\n \n \n \n \n \n \n \n );\n}\n\nexport default WSAudioPlayerRate;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\WSAudioPlayerSegment.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'handleRemoveNextSplit', 'handleSplit', 'subscribe', and 'unsubscribe'. Either include them or remove the dependency array.","line":92,"column":6,"nodeType":"ArrayExpression","endLine":92,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [handleRemoveNextSplit, handleSplit, subscribe, unsubscribe]","fix":{"range":[3153,3155],"text":"[handleRemoveNextSplit, handleSplit, subscribe, unsubscribe]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\WSAudioPlayerSegmentRecordedLock.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\WSAudioPlayerSilence.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\WSAudioPlayerZoom.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setZoom'. Either include it or remove the dependency array.","line":46,"column":6,"nodeType":"ArrayExpression","endLine":46,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [curPx, setZoom]","fix":{"range":[1625,1632],"text":"[curPx, setZoom]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setZoom'. Either include it or remove the dependency array.","line":70,"column":6,"nodeType":"ArrayExpression","endLine":70,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [fillPx, setZoom]","fix":{"range":[2524,2532],"text":"[fillPx, setZoom]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'handleZoomIn', 'handleZoomOut', 'subscribe', and 'unsubscribe'. Either include them or remove the dependency array.","line":101,"column":6,"nodeType":"ArrayExpression","endLine":101,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [handleZoomIn, handleZoomOut, subscribe, unsubscribe]","fix":{"range":[3392,3394],"text":"[handleZoomIn, handleZoomOut, subscribe, unsubscribe]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\WSSegmentParameters.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\WhichExportDlg.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\apmGraphic.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\apmGraphic.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\downloadMediaFileName.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\downloadMediaFileName.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\fontSpace.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\getRefFilter.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\getRefFilter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\isUsableGraphicUrl.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\isUsableGraphicUrl.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\resolveSectionForRecId.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\resolveSectionForRecId.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\segmentBoundaryLocks.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\shouldStartItfSyncUpload.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\shouldStartItfSyncUpload.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\useAdminTeams.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\useAudioDownload.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchMediaUrl', 'showMessage', 'ts.fileNotFound', and 'updateBlobUrl'. Either include them or remove the dependency array.","line":100,"column":6,"nodeType":"ArrayExpression","endLine":100,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [fetchMediaUrl, mediaState, showMessage, ts.fileNotFound, updateBlobUrl]","fix":{"range":[3195,3207],"text":"[fetchMediaUrl, mediaState, showMessage, ts.fileNotFound, updateBlobUrl]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchMediaUrl' and 'updateBlobUrl'. Either include them or remove the dependency array.","line":112,"column":6,"nodeType":"ArrayExpression","endLine":112,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [blobUrl, audName, fetchMediaUrl, updateBlobUrl]","fix":{"range":[3505,3523],"text":"[blobUrl, audName, fetchMediaUrl, updateBlobUrl]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\useGraphicPicker.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\useGraphicPicker.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\usePaneWidth.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\usePaneWidth.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setDimensions'. Either include it or remove the dependency array.","line":54,"column":6,"nodeType":"ArrayExpression","endLine":54,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [setDimensions]","fix":{"range":[1872,1874],"text":"[setDimensions]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\components\\useTitleSave.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\GlobalContext.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\HotKeyContext.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'key' is defined but never used. Allowed unused args must match /^_/u.","line":9,"column":15,"nodeType":null,"messageId":"unusedVar","endLine":9,"endColumn":18,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'cb' is defined but never used. Allowed unused args must match /^_/u.","line":9,"column":28,"nodeType":null,"messageId":"unusedVar","endLine":9,"endColumn":30,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'key' is defined but never used. Allowed unused args must match /^_/u.","line":11,"column":17,"nodeType":null,"messageId":"unusedVar","endLine":11,"endColumn":20,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'key' is defined but never used. Allowed unused args must match /^_/u.","line":13,"column":20,"nodeType":null,"messageId":"unusedVar","endLine":13,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'handleKey'. Either include it or remove the dependency array.","line":53,"column":6,"nodeType":"ArrayExpression","endLine":53,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [handleKey]","fix":{"range":[1606,1608],"text":"[handleKey]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\PassageDetailContext.tsx","messages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'forceClearPending'. Either include it or remove the dependency array.","line":1269,"column":6,"nodeType":"ArrayExpression","endLine":1269,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [forceClearPending]","fix":{"range":[40090,40092],"text":"[forceClearPending]"}}]}],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'index' is defined but never used. Allowed unused args must match /^_/u.","line":213,"column":54,"nodeType":null,"messageId":"unusedVar","endLine":213,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'cb' is defined but never used. Allowed unused args must match /^_/u.","line":214,"column":17,"nodeType":null,"messageId":"unusedVar","endLine":214,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'state.psgCompleted'. Either include it or remove the dependency array.","line":1118,"column":6,"nodeType":"ArrayExpression","endLine":1118,"endColumn":77,"suggestions":[{"desc":"Update the dependencies array to be: [memory, pasId, passages, sections, state.passage.id, state.psgCompleted, state.section.id]","fix":{"range":[35516,35587],"text":"[memory, pasId, passages, sections, state.passage.id, state.psgCompleted, state.section.id]"}}],"suppressions":[{"kind":"directive","justification":"sync from orbit only; see comment above"}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'fetchBooks'. Either include it or remove the dependency array.","line":1129,"column":6,"nodeType":"ArrayExpression","endLine":1129,"endColumn":38,"suggestions":[{"desc":"Update the dependencies array to be: [lang, booksLoaded, allBookData, fetchBooks]","fix":{"range":[35837,35869],"text":"[lang, booksLoaded, allBookData, fetchBooks]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'errorReporter', 'sharedStr.fileNotFound', and 'showMessage'. Either include them or remove the dependency array.","line":1159,"column":6,"nodeType":"ArrayExpression","endLine":1159,"endColumn":17,"suggestions":[{"desc":"Update the dependencies array to be: [blobState, errorReporter, sharedStr.fileNotFound, showMessage]","fix":{"range":[36747,36758],"text":"[blobState, errorReporter, sharedStr.fileNotFound, showMessage]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'errorReporter', 'setSaveResult', and 'showMessage'. Either include them or remove the dependency array.","line":1168,"column":6,"nodeType":"ArrayExpression","endLine":1168,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [errorReporter, saveResult, setSaveResult, showMessage]","fix":{"range":[36990,37002],"text":"[errorReporter, saveResult, setSaveResult, showMessage]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'artifactTypes', 'categories', 'getProjectResources', 'localizedArtifactCategory', 'localizedArtifactType', 'memory', 'passages', 'setSelected', 'state.index', 'state.playerMediafile?.id', 'state.selected', 'state.tool', and 'user'. Either include them or remove the dependency array.","line":1233,"column":6,"nodeType":"ArrayExpression","endLine":1233,"endColumn":58,"suggestions":[{"desc":"Update the dependencies array to be: [sectionResources, mediafiles, pasId, userResources, memory, passages, localizedArtifactCategory, localizedArtifactType, getProjectResources, artifactTypes, categories, user, state.selected, state.index, state.tool, state.playerMediafile?.id, setSelected]","fix":{"range":[38941,38993],"text":"[sectionResources, mediafiles, pasId, userResources, memory, passages, localizedArtifactCategory, localizedArtifactType, getProjectResources, artifactTypes, categories, user, state.selected, state.index, state.tool, state.playerMediafile?.id, setSelected]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setItemPlaying'. Either include it or remove the dependency array.","line":1248,"column":6,"nodeType":"ArrayExpression","endLine":1248,"endColumn":22,"suggestions":[{"desc":"Update the dependencies array to be: [setItemPlaying, state.playItem]","fix":{"range":[39505,39521],"text":"[setItemPlaying, state.playItem]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'state.orgWorkflowSteps'. Either include it or remove the dependency array.","line":1255,"column":6,"nodeType":"ArrayExpression","endLine":1255,"endColumn":24,"suggestions":[{"desc":"Update the dependencies array to be: [filteredOrgSteps, state.orgWorkflowSteps]","fix":{"range":[39750,39768],"text":"[filteredOrgSteps, state.orgWorkflowSteps]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'handleSetCurrentStep' and 'state'. Either include them or remove the dependency array.","line":1282,"column":6,"nodeType":"ArrayExpression","endLine":1282,"endColumn":69,"suggestions":[{"desc":"Update the dependencies array to be: [state.currentstep, state.psgCompleted, state.orgWorkflowSteps, state, handleSetCurrentStep]","fix":{"range":[40495,40558],"text":"[state.currentstep, state.psgCompleted, state.orgWorkflowSteps, state, handleSetCurrentStep]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* eslint-disable @typescript-eslint/no-unused-vars */\nimport React, {\n useState,\n useEffect,\n useRef,\n useContext,\n useCallback,\n} from 'react';\n// see: https://upmostly.com/tutorials/how-to-use-the-usecontext-hook-in-react\nimport { useGetGlobal, useGlobal } from '../context/useGlobal';\nimport { useRenderProfiler } from '../utils/perf';\nimport { useParams } from 'react-router-dom';\nimport { shallowEqual } from 'react-redux';\nimport {\n IState,\n MediaFile,\n MediaFileD,\n ISharedStrings,\n Passage,\n PassageD,\n Section,\n SectionD,\n BookName,\n OrgWorkflowStep,\n OrgWorkflowStepD,\n SectionResourceUser,\n ArtifactType,\n ArtifactCategory,\n IWorkflowStepsStrings,\n IPassageDetailStepCompleteStrings,\n StepComplete,\n SectionResourceD,\n SharedResourceD,\n} from '../model';\nimport { AddPassageStateChangeToOps } from '../crud/updatePassageState';\nimport { ArtifactTypeSlug } from '../crud/artifactTypeSlug';\nimport { ToolSlug } from '../crud/toolSlug';\nimport { findRecord } from '../crud/tryFindRecord';\nimport { getAllMediaRecs } from '../crud/media';\nimport { getStepComplete } from '../crud/getStepComplete';\nimport { getTool } from '../crud/useStepTool';\nimport { nextPasId } from '../crud/nextPasId';\nimport {\n orgDefaultWorkflowProgression,\n WorkflowProgression,\n} from '../crud/useOrgDefaults';\nimport { related } from '../crud/related';\nimport { remoteId, remoteIdGuid } from '../crud/remoteId';\nimport { useArtifactCategory } from '../crud/useArtifactCategory';\nimport { useArtifactType } from '../crud/useArtifactType';\nimport { BlobStatus, useFetchMediaBlob } from '../crud/useFetchMediaBlob';\nimport { useFilteredSteps } from '../crud/useFilteredSteps';\nimport { useOrgDefaults } from '../crud/useOrgDefaults';\nimport { useOrgWorkflowSteps } from '../crud/useOrgWorkflowSteps';\nimport {\n BOLD_WORKFLOW_PROCESS,\n useTeamWorkflowProcess,\n} from '../crud/useTeamWorkflowProcess';\nimport StickyRedirect from '../components/StickyRedirect';\nimport {\n infoMsg,\n logError,\n needsStepNavigationConfirm,\n prettySegment,\n rememberCurrentPassage,\n Severity,\n} from '../utils';\nimport { useSnackBar } from '../hoc/SnackBar';\nimport * as actions from '../store';\nimport LimitedMediaPlayer from '../components/LimitedMediaPlayer';\nimport {\n getResources,\n mediaRows,\n oneMediaRow,\n resourceRows,\n} from '../components/PassageDetail/Internalization';\nimport Confirm from '../components/AlertDialog';\nimport StepNavigationConfirmDialog from '../components/PassageDetail/StepNavigationConfirmDialog';\nimport { getNextStep } from '../crud/getNextStep';\nimport { UnsavedContext } from './UnsavedContext';\nimport { IRegion, IRegionParams } from '../crud/useWavesurferRegions';\nimport { UpdateLastModifiedBy } from '../model/baseModel';\nimport { IMarker } from '../crud/useWaveSurfer';\nimport { useSelector } from 'react-redux';\nimport {\n passageDetailStepCompleteSelector,\n sharedSelector,\n workflowStepsSelector,\n} from '../selector';\nimport { useDispatch } from 'react-redux';\nimport {\n RecordKeyMap,\n RecordOperation,\n RecordTransformBuilder,\n} from '@orbit/records';\nimport { useOrbitData } from '../hoc/useOrbitData';\nimport {\n projDefSectionMap,\n useProjectDefaults,\n} from '../crud/useProjectDefaults';\nimport { usePassageNavigate } from '../components/PassageDetail/usePassageNavigate';\nimport { useProjectPermissions } from '../utils/useProjectPermissions';\nimport { PlayInPlayer } from './PlayInPlayer';\nimport { SectionArray } from '@model/SectionArray';\nimport { boldDefaultSegParams } from '../components/PassageDetail/carefulSpeech/boldCarefulSpeechSegParams';\nimport { isPassageNavigationBlocked } from './passageDetailNavigationBlocked';\n\nexport interface IRow {\n id: string;\n sequenceNum: number;\n version: number;\n mediafile: MediaFileD;\n playItem: string;\n artifactName: string;\n artifactType: string;\n /** Raw artifact type slug (e.g. 'resource', 'sharedresource') behind artifactType. */\n artifactTypeSlug: string;\n /** Media is (or derives from) a general/project resource -- see generalResourceMedia. */\n isGeneralResource: boolean;\n artifactCategory: string;\n done: boolean;\n editAction: React.JSX.Element | null;\n resource: SectionResourceD | null;\n passageId: string;\n isVernacular: boolean;\n isResource: boolean;\n isComment: boolean;\n isKeyTerm: boolean;\n isText: boolean;\n sourceVersion: number;\n}\n\nexport interface SimpleWf {\n id: string;\n label: string;\n}\nconst initState = {\n passage: {} as PassageD,\n section: {} as SectionD,\n sharedResource: {} as SharedResourceD,\n currentstep: '',\n tool: ToolSlug.Discuss,\n orgWorkflowSteps: [] as OrgWorkflowStepD[],\n setOrgWorkflowSteps: (_steps: OrgWorkflowStep[]) => {},\n setCurrentStep: (_step: string) => {}, //what the user is looking at\n firstStepIndex: -1,\n setFirstStepIndex: (_step: number) => {},\n index: 0, //row index?\n mediafileId: '', //This is the latest vernacular\n selected: '',\n setSelected: (\n _selected: string,\n _inPlayer: PlayInPlayer,\n _rowData?: IRow[]\n ) => {},\n setMediaSelected: (_id: string, _start: number, _end: number) => {},\n playerMediafile: undefined as MediaFile | undefined, //passagedetailPlayer id\n playing: false, //vernacular in wavesurfer\n setPlaying: (_playing: boolean) => {},\n itemPlaying: false, //resource, bt, retell etc\n setItemPlaying: (_playing: boolean) => {},\n playItem: '', //resource\n setPlayItem: (_item: string) => {},\n commentPlaying: false,\n setCommentPlaying: (_playing: boolean, _ended?: boolean) => {},\n commentPlayId: '',\n setCommentPlayId: (_mediaId: string) => {},\n oldVernacularPlayItem: '',\n oldVernacularStart: 0,\n oldVernacularPlaying: false,\n handleOldVernacularPlayEnd: () => {},\n rowData: Array(),\n\n loading: false,\n audioBlob: undefined as Blob | undefined,\n pdBusy: false,\n setPDBusy: (_pdBusy: boolean) => {},\n allBookData: Array(),\n workflow: Array(),\n psgCompleted: [] as StepComplete[],\n setStepComplete: async (\n _stepId: string,\n _complete: boolean,\n _psgCompleted?: StepComplete[]\n ): Promise => {},\n setStepCompleteTo: async (_stepId: string) => {},\n gotoNextStep: () => {},\n stepComplete: (_stepId: string) => {\n return false;\n },\n discussionSize: { width: 450, height: 900 },\n setDiscussionSize: (_size: { width: number; height: number }) => {},\n chooserSize: 48,\n setChooserSize: (_size: number) => {},\n defaultFilename: '',\n uploadItem: '',\n currentSegment: '',\n currentSegmentIndex: -1,\n /**\n * Increments on every actual change of the current segment.\n *\n * `currentSegmentIndex` cannot be used to notice a change, because its\n * numbering is not agreed: the waveform writes a 1-based sorted position\n * (0 meaning \"whole\") via usePlayerLogic, Mark Verses writes a table row, and\n * PassageDetailGuidedPhraseRecord writes a 0-based clause index. A real move\n * can therefore arrive carrying the number the previous writer used — e.g.\n * selecting segment 2 (waveform: 1+1) right after the step selected segment 3\n * (step: 2) — and an effect watching the index alone never re-runs.\n *\n * Watch this instead when you only need to know that the selection moved.\n */\n currentSegmentSeq: 0,\n setCurrentSegment: (_segment: IRegion | undefined, index: number) => {}, //replace the above two\n setupLocate: (cb?: (segments: string) => void) => {},\n getCurrentSegment: () => undefined as IRegion | undefined,\n setPlayerSegments: (_segments: string) => {},\n recording: false,\n setRecording: (_recording: boolean) => {},\n commentRecording: false,\n setCommentRecording: (_commentRecording: boolean) => {},\n isNavigationBlocked: () => false,\n handleItemPlayEnd: () => {},\n handleItemTogglePlay: () => {},\n handleCommentPlayEnd: () => {},\n handleCommentTogglePlay: () => {},\n discussionMarkers: [] as IMarker[],\n setDiscussionMarkers: (_markers: IMarker[]) => {},\n handleHighlightDiscussion: (_time: number | undefined) => {},\n highlightDiscussion: undefined as number | undefined,\n refresh: 0,\n prjId: '',\n forceRefresh: (_rowData?: IRow[]) => {},\n sectionArr: [] as SectionArray,\n toggleDone: (_id: string) => {},\n canPublish: false,\n discussOpen: false,\n setDiscussOpen: (_discussOpen: boolean) => {},\n isBoldWorkflow: false,\n promptPlaybackComplete: false,\n setPromptPlaybackComplete: (_complete: boolean) => {},\n promptDockedRecordButton: null as React.ReactNode | null,\n setPromptDockedRecordButton: (_node: React.ReactNode | null) => {},\n promptDockedRecordFooterVersion: 0,\n carefulSpeechSegParams: boldDefaultSegParams,\n setCarefulSpeechSegParams: (_params: IRegionParams) => {},\n hideMobileHeader: false,\n setHideMobileHeader: (_hide: boolean) => {},\n};\n\nexport type ICtxState = typeof initState;\n\ninterface IContext {\n state: ICtxState;\n setState: React.Dispatch>;\n}\n\nconst PassageDetailContext = React.createContext({\n state: initState as ICtxState,\n setState: () => {},\n} as IContext);\n\ninterface IProps {\n children: React.ReactElement;\n}\nconst PassageDetailProvider = (props: IProps) => {\n useRenderProfiler('PassageDetailProvider');\n const passages = useOrbitData('passage');\n const sections = useOrbitData('section');\n const mediafiles = useOrbitData('mediafile');\n const artifactTypes = useOrbitData('artifacttype');\n const categories = useOrbitData('artifactcategory');\n const userResources = useOrbitData(\n 'sectionresourceuser'\n );\n const sectionResources = useOrbitData('sectionresource');\n const wfStr: IWorkflowStepsStrings = useSelector(\n workflowStepsSelector,\n shallowEqual\n );\n const sharedStr: ISharedStrings = useSelector(sharedSelector, shallowEqual);\n const stepCompleteStr: IPassageDetailStepCompleteStrings = useSelector(\n passageDetailStepCompleteSelector,\n shallowEqual\n );\n const lang = useSelector((state: IState) => state.strings.lang);\n const allBookData = useSelector((state: IState) => state.books.bookData);\n const booksLoaded = useSelector((state: IState) => state.books.loaded);\n const dispatch = useDispatch();\n const fetchBooks = (lang: string) =>\n dispatch(actions.fetchBooks(lang) as any);\n const { pasId, prjId } = useParams();\n const [memory] = useGlobal('memory');\n const [user] = useGlobal('user');\n const [org] = useGlobal('organization');\n const [errorReporter] = useGlobal('errorReporter');\n const [saveResult, setSaveResult] = useGlobal('saveResult'); //verified this is not used in a function 2/18/25\n const [confirm, setConfirm] = useState('');\n const [incompleteNavTarget, setIncompleteNavTarget] = useState('');\n const view = React.useRef('');\n const { showMessage } = useSnackBar();\n const [plan] = useGlobal('plan'); //will be constant here\n const { getProjectDefault } = useProjectDefaults();\n const [state, setState] = useState({\n ...initState,\n allBookData,\n prjId: prjId ?? '',\n });\n const [blobState, fetchBlob] = useFetchMediaBlob();\n const fetching = useRef('');\n const segmentsCb = useRef<((segments: string) => void) | undefined>(\n undefined\n );\n const filteredOrgSteps = useFilteredSteps();\n const { localizedArtifactType, getTypeId } = useArtifactType();\n const { localizedArtifactCategory } = useArtifactCategory();\n const { localizedWorkStep } = useOrgWorkflowSteps();\n const mediaStart = useRef(undefined);\n const mediaEnd = useRef(undefined);\n const mediaPosition = useRef(undefined);\n const currentSegmentRef = useRef(undefined);\n const currentSegmentIndexRef = useRef(-1);\n /** Change token for the current segment; see initState.currentSegmentSeq. */\n const currentSegmentSeqRef = useRef(0);\n const { startSave, startClear, waitForSave, forceClearPending } =\n useContext(UnsavedContext).state;\n const highlightRef = useRef(undefined);\n const refreshRef = useRef(0);\n const recordingRef = useRef(false);\n const commentRecordingRef = useRef(false);\n const settingSegmentRef = useRef(false);\n const inPlayerRef = useRef(undefined);\n const { getOrgDefault } = useOrgDefaults();\n const getGlobal = useGetGlobal();\n const { canPublish } = useProjectPermissions();\n const teamWorkflowProcess = useTeamWorkflowProcess(org);\n const isBoldWorkflow = teamWorkflowProcess === BOLD_WORKFLOW_PROCESS;\n\n const stepComplete = (stepid: string) => {\n stepid =\n remoteId('orgworkflowstep', stepid, memory?.keyMap as RecordKeyMap) ||\n stepid;\n const step = state.psgCompleted.find((s) => s.stepid === stepid);\n return Boolean(step?.complete);\n };\n\n const isNavigationBlocked = () =>\n isPassageNavigationBlocked(\n recordingRef.current,\n commentRecordingRef.current\n );\n\n const handleSetCurrentStep = (stepId: string) => {\n const step = state.orgWorkflowSteps.find((s) => s.id === stepId);\n const tool = getTool(step?.attributes?.tool) as ToolSlug;\n setCurrentSegment(undefined, 0);\n // Clear discussion locate without handleHighlightDiscussion — that helper\n // no-ops while settingSegmentRef is set (mid-locate/play), which is exactly\n // when step switches hang after the compass button.\n highlightRef.current = undefined;\n settingSegmentRef.current = false;\n\n setState((state: ICtxState) => {\n return {\n ...state,\n currentstep: stepId,\n tool,\n playing: false,\n itemPlaying: false,\n commentPlaying: false,\n oldVernacularPlaying: false,\n playItem: '',\n commentPlayId: '',\n oldVernacularPlayItem: '',\n highlightDiscussion: undefined,\n };\n });\n\n if (step && tool !== ToolSlug.Resource && tool !== ToolSlug.Transcribe) {\n //this does a bunch of stuff...don't just set it in the state above...\n if (\n state.rowData.length > 0 &&\n state.rowData[0] !== undefined &&\n state.rowData[0].isVernacular\n ) {\n setSelected(state.rowData[0].id, PlayInPlayer.yes);\n } else setSelected('', PlayInPlayer.yes);\n }\n segmentsCb.current = undefined;\n };\n\n const attemptSetCurrentStep = (stepId: string) => {\n if (isNavigationBlocked()) return;\n if (needsStepNavigationConfirm(state.currentstep, stepId, stepComplete)) {\n setIncompleteNavTarget(stepId);\n return;\n }\n handleSetCurrentStep(stepId);\n };\n\n const setCurrentStep = (stepId: string) => {\n if (isNavigationBlocked()) return;\n if (getGlobal('changed')) {\n setConfirm(stepId);\n } else {\n attemptSetCurrentStep(stepId);\n }\n };\n\n const passageNavigate = usePassageNavigate(\n () => {},\n setCurrentStep,\n isNavigationBlocked\n );\n\n const forceRefresh = (rowData?: IRow[]) => {\n refreshRef.current = refreshRef.current + 1;\n setState((state: ICtxState) => {\n return {\n ...state,\n refresh: refreshRef.current,\n rowData: rowData ?? state.rowData,\n };\n });\n };\n\n const setFirstStepIndex = (stepIndex: number) => {\n setState((state: ICtxState) => {\n return {\n ...state,\n firstStepIndex: stepIndex,\n };\n });\n };\n\n const finishStepConfirm = (target: string) => {\n try {\n attemptSetCurrentStep(target);\n } finally {\n setConfirm('');\n }\n };\n\n const handleConfirmStep = () => {\n const target = confirm;\n startSave();\n // Do not pass finishStepConfirm into waitForSave — its blanket catch turns\n // callback throws into 'Timed Out' and would re-run navigation below.\n void waitForSave(undefined, 400).then(\n () => finishStepConfirm(target),\n (err) => {\n showMessage(err?.message || String(err));\n setConfirm('');\n }\n );\n };\n\n const handleRefuseStep = () => {\n const target = confirm;\n // forceClearPending on wait failure for orphaned tools (unmounted after mid-play step switch).\n startClear();\n void waitForSave(undefined, 15).then(\n () => finishStepConfirm(target),\n (err) => {\n showMessage(err?.message || String(err));\n forceClearPending();\n finishStepConfirm(target);\n }\n );\n };\n\n const setDiscussionSize = (discussionSize: {\n width: number;\n height: number;\n }) => {\n setState((state: ICtxState) => {\n return { ...state, discussionSize };\n });\n };\n\n const setChooserSize = (chooserSize: number) => {\n setState((state: ICtxState) => {\n return { ...state, chooserSize };\n });\n };\n\n const setDiscussOpen = useCallback((discussOpen: boolean) => {\n setState((state: ICtxState) => {\n if (state.discussOpen === discussOpen) {\n return state;\n }\n return { ...state, discussOpen };\n });\n }, []);\n\n const setHideMobileHeader = useCallback((hideMobileHeader: boolean) => {\n setState((state: ICtxState) => {\n if (state.hideMobileHeader === hideMobileHeader) {\n return state;\n }\n return { ...state, hideMobileHeader };\n });\n }, []);\n\n const setPromptPlaybackComplete = useCallback(\n (promptPlaybackComplete: boolean) => {\n setState((state: ICtxState) => {\n if (state.promptPlaybackComplete === promptPlaybackComplete) {\n return state;\n }\n return { ...state, promptPlaybackComplete };\n });\n },\n []\n );\n\n const promptDockedRecordButtonRef = useRef(null);\n const [promptDockedRecordFooterVersion, setPromptDockedRecordFooterVersion] =\n useState(0);\n\n const setPromptDockedRecordButton = useCallback(\n (node: React.ReactNode | null) => {\n promptDockedRecordButtonRef.current = node;\n setPromptDockedRecordFooterVersion((v) => v + 1);\n },\n []\n );\n\n const setRecording = (recording: boolean) => {\n recordingRef.current = recording;\n setState((state: ICtxState) => {\n return {\n ...state,\n playing: false, //stop the vernacular\n itemPlaying: false,\n commentPlaying: false,\n oldVernacularPlaying: false,\n recording,\n };\n });\n };\n const setCommentRecording = (commentRecording: boolean) => {\n commentRecordingRef.current = commentRecording;\n setState((state: ICtxState) => {\n return {\n ...state,\n playing: false, //stop the vernacular\n itemPlaying: false,\n commentPlaying: false,\n oldVernacularPlaying: false,\n commentRecording,\n };\n });\n };\n\n //this is for the PD Player only\n const setPlaying = (playing: boolean) => {\n //if this is called from a callback, we don't know the state\n //if (playing !== state.playing) {\n if (playing)\n setState((state: ICtxState) => {\n return {\n ...state,\n playing,\n itemPlaying: false,\n commentPlaying: false,\n oldVernacularPlaying: false,\n oldVernacularPlayItem: '',\n oldVernacularStart: 0,\n };\n });\n else\n setState((state: ICtxState) => {\n if (!state.playing) return state;\n return {\n ...state,\n playing,\n };\n });\n };\n const setItemPlaying = (itemPlaying: boolean) => {\n if (itemPlaying !== state.itemPlaying) {\n setState((state: ICtxState) => {\n return {\n ...state,\n itemPlaying,\n playing: itemPlaying ? false : state.playing,\n commentPlaying: itemPlaying ? false : state.commentPlaying,\n oldVernacularPlaying: itemPlaying\n ? false\n : state.oldVernacularPlaying,\n oldVernacularPlayItem: itemPlaying ? '' : state.oldVernacularPlayItem,\n oldVernacularStart: itemPlaying ? 0 : state.oldVernacularStart,\n };\n });\n }\n };\n const setCommentPlaying = (\n commentPlaying: boolean,\n ended: boolean = false\n ) => {\n if (commentPlaying !== state.commentPlaying) {\n setState((state: ICtxState) => {\n return {\n ...state,\n commentPlaying,\n commentPlayId: ended ? '' : state.commentPlayId,\n playing: commentPlaying ? false : state.playing,\n itemPlaying: commentPlaying ? false : state.itemPlaying,\n oldVernacularPlaying: commentPlaying\n ? false\n : state.oldVernacularPlaying,\n oldVernacularPlayItem: commentPlaying\n ? ''\n : state.oldVernacularPlayItem,\n };\n });\n }\n };\n\n const handleItemPlayEnd = () => {\n setItemPlaying(false);\n oldVernReset();\n };\n const handleItemTogglePlay = () => {\n setItemPlaying(!state.itemPlaying);\n };\n const handleCommentPlayEnd = () => {\n if (state.commentPlaying) setCommentPlaying(false, true);\n else setCommentPlayId('');\n };\n\n const handleCommentTogglePlay = () => {\n setCommentPlaying(!state.commentPlaying);\n };\n const handleOldVernacularPlayEnd = () => {\n mediaStart.current = undefined;\n mediaEnd.current = undefined;\n setState((state: ICtxState) => {\n return {\n ...state,\n oldVernacularPlaying: false,\n oldVernacularPlayItem: '',\n oldVernacularStart: 0,\n };\n });\n };\n const setPDBusy = (busy: boolean) => {\n setState((state: ICtxState) => {\n return {\n ...state,\n pdBusy: busy,\n };\n });\n };\n\n const setCarefulSpeechSegParams = (params: IRegionParams) => {\n setState((state: ICtxState) => {\n return { ...state, carefulSpeechSegParams: params };\n });\n };\n\n const setDiscussionMarkers = (discussionMarkers: IMarker[]) => {\n setState((state: ICtxState) => {\n return { ...state, discussionMarkers };\n });\n };\n const handleHighlightDiscussion = (time: number | undefined) => {\n if (settingSegmentRef.current) return;\n\n settingSegmentRef.current = true;\n if (highlightRef.current !== time) {\n highlightRef.current = time;\n setState((state: ICtxState) => {\n return {\n ...state,\n highlightDiscussion: time,\n };\n });\n } else if (time !== undefined) {\n //force refresh if they've hit the same locate button again\n refreshRef.current = refreshRef.current + 1;\n setState((state: ICtxState) => {\n return { ...state, refresh: refreshRef.current, playing: false };\n });\n } else settingSegmentRef.current = false;\n };\n\n const gotoNextStep = () => {\n const gotoNextPassage =\n !isBoldWorkflow &&\n getOrgDefault(orgDefaultWorkflowProgression) !== WorkflowProgression.Step;\n const nextpsg = gotoNextPassage\n ? nextPasId(state.section, state.passage.id, memory)\n : undefined;\n if (nextpsg && nextpsg !== state.passage?.keys?.remoteId) {\n rememberCurrentPassage(memory, nextpsg);\n passageNavigate(`/detail/${prjId}/${nextpsg}`);\n } else {\n setCurrentStep('');\n } // setting to empty jumps to first uncompleted\n };\n const setStepComplete = async (\n stepid: string,\n complete: boolean,\n psgCompleted?: StepComplete[]\n ) => {\n if (stepid === '') return;\n const completed = psgCompleted ?? [...state.psgCompleted];\n const remId =\n remoteId('orgworkflowstep', stepid, memory?.keyMap as RecordKeyMap) ||\n stepid;\n const step = completed.find((s) => s.stepid === remId);\n const rec = findRecord(\n memory,\n 'orgworkflowstep',\n stepid\n ) as OrgWorkflowStep;\n if (step) {\n step.complete = complete;\n } else {\n completed.push({ stepid: remId, complete, name: rec.attributes.name });\n }\n const recId = {\n type: 'passage',\n id:\n remoteIdGuid('passage', pasId ?? '', memory?.keyMap as RecordKeyMap) ||\n pasId ||\n '',\n };\n const curPassage = findRecord(memory, 'passage', recId.id) as Passage;\n const curCompleteStr = curPassage?.attributes.stepComplete;\n let stepComplete = {};\n try {\n stepComplete = JSON.parse(curCompleteStr || '{}');\n } catch (err) {\n logError(\n Severity.error,\n errorReporter,\n infoMsg(err as Error, 'Json conversion error')\n );\n }\n const tb = new RecordTransformBuilder();\n const ops = [] as RecordOperation[];\n ops.push(\n tb\n .replaceAttribute(\n recId,\n 'stepComplete',\n JSON.stringify({ ...stepComplete, completed })\n )\n .toOperation()\n );\n ops.push(...UpdateLastModifiedBy(tb, recId, user));\n AddPassageStateChangeToOps(\n tb,\n ops,\n recId.id,\n '',\n `${\n complete ? stepCompleteStr.title : stepCompleteStr.incomplete\n } : ${localizedWorkStep(rec.attributes.name)}`,\n user,\n memory\n );\n await memory.update(ops);\n setState((state: ICtxState) => ({ ...state, psgCompleted: completed }));\n };\n const setStepCompleteTo = async (stepid: string) => {\n if (stepid === '') return;\n const completed: StepComplete[] = [];\n const steps = state.orgWorkflowSteps.sort(\n (a, b) => a.attributes.sequencenum - b.attributes.sequencenum\n );\n let rec;\n for (const step of steps) {\n const remId =\n remoteId('orgworkflowstep', step.id, memory.keyMap as RecordKeyMap) ||\n step.id;\n rec = findRecord(memory, 'orgworkflowstep', step.id) as OrgWorkflowStep;\n completed.push({\n stepid: remId,\n complete: true,\n name: rec.attributes.name,\n });\n if (step.id === stepid) break;\n }\n const recId = {\n type: 'passage',\n id:\n remoteIdGuid('passage', pasId ?? '', memory.keyMap as RecordKeyMap) ||\n pasId ||\n '',\n };\n const tb = new RecordTransformBuilder();\n const ops = [] as RecordOperation[];\n ops.push(\n tb\n .replaceAttribute(recId, 'stepComplete', JSON.stringify({ completed }))\n .toOperation()\n );\n ops.push(...UpdateLastModifiedBy(tb, recId, user));\n AddPassageStateChangeToOps(\n tb,\n ops,\n recId.id,\n '',\n `${stepCompleteStr.title} : ${localizedWorkStep(\n rec?.attributes?.name ?? ''\n )}`,\n user,\n memory\n );\n await memory.update(ops);\n setState((state: ICtxState) => ({ ...state, psgCompleted: completed }));\n };\n\n const handleIncompleteNavCancel = () => {\n setIncompleteNavTarget('');\n };\n\n const handleIncompleteNavContinue = () => {\n if (isNavigationBlocked()) return;\n const target = incompleteNavTarget;\n setIncompleteNavTarget('');\n if (target) handleSetCurrentStep(target);\n };\n\n const handleIncompleteNavComplete = () => {\n if (isNavigationBlocked()) return;\n const target = incompleteNavTarget;\n const fromStep = state.currentstep;\n setIncompleteNavTarget('');\n if (!target || !fromStep) return;\n void waitForSave(async () => {\n await setStepComplete(fromStep, true);\n handleSetCurrentStep(target);\n }, 200);\n };\n\n const incompleteNavMessage = (() => {\n if (!incompleteNavTarget) return '';\n const step = state.orgWorkflowSteps.find((s) => s.id === state.currentstep);\n const label = step\n ? localizedWorkStep(step.attributes.name)\n : state.currentstep;\n return wfStr.incompleteStepNavigate.replace('{0}', label);\n })();\n\n const getProjectResources = () => {\n const typeId = getTypeId(ArtifactTypeSlug.ProjectResource);\n return mediafiles.filter(\n (m) =>\n related(m, 'plan') === plan && related(m, 'artifactType') === typeId\n );\n };\n\n const setSelected = (\n selected: string,\n inPlayer: PlayInPlayer,\n rowData: IRow[] = state.rowData\n ) => {\n let i = rowData.findIndex((r) => r.mediafile.id === selected);\n let newRows: IRow[] = [];\n\n if (i < 0) {\n // useOrbitData's snapshot can lag a just-created mediafile (deferred\n // general-resource upload → configure). Fall back to the cache.\n const media =\n mediafiles.find((m) => m.id === selected) ??\n (findRecord(memory, 'mediafile', selected) as MediaFileD | undefined);\n if (media) {\n newRows = oneMediaRow({\n newRow: state.rowData,\n r: null,\n media,\n sourceversion: 0,\n mediafiles,\n artifactTypes,\n categories,\n userResources,\n user,\n localizedCategory: localizedArtifactCategory,\n localizedType: localizedArtifactType,\n });\n i = newRows.length - 1;\n } else {\n oldVernReset();\n fetchBlob('');\n setState((state: ICtxState) => {\n return {\n ...state,\n audioBlob: undefined,\n index: -1,\n selected,\n playerMediafile: undefined,\n playing: false,\n itemPlaying: false,\n commentPlaying: false,\n playItem: '',\n commentPlayId: '',\n loading: false,\n };\n });\n return;\n }\n }\n // i indexes newRows when a row was just built for this media.\n const r = (newRows.length > 0 ? newRows : rowData)[i] as IRow;\n let resetBlob = false;\n //if this is a file that will be played in the wavesurfer..fetch it\n if (inPlayer === PlayInPlayer.yes) {\n inPlayerRef.current = r.mediafile.id;\n if (\n blobState.id !== r.mediafile.id &&\n fetching.current !== r.mediafile.id\n ) {\n fetching.current = r.mediafile.id;\n fetchBlob(r.mediafile.id);\n resetBlob = true;\n }\n\n if (resetBlob) currentSegmentRef.current = undefined;\n const rows = newRows.length > 0 ? newRows : rowData;\n setState((state: ICtxState) => {\n return {\n ...state,\n audioBlob: resetBlob ? undefined : state.audioBlob,\n index: i,\n selected,\n playerMediafile: (rows[i] as IRow).mediafile,\n playing: false,\n loading: fetching.current !== '',\n rowData: rows,\n currentSegment: resetBlob ? '' : state.currentSegment,\n currentSegmentIndex: resetBlob ? 0 : state.currentSegmentIndex,\n };\n });\n } else if (mediaStart.current !== undefined && !r.isResource) {\n //play just the segment of an old one\n setState((state: ICtxState) => {\n return {\n ...state,\n index: i,\n selected,\n playing: false,\n commentPlaying: false,\n itemPlaying: false,\n oldVernacularPlayItem: r.mediafile.id,\n oldVernacularStart: mediaStart.current || 0,\n rowData: newRows.length > 0 ? newRows : rowData,\n };\n });\n } else if (r.isComment || r.isKeyTerm) {\n setState((state: ICtxState) => {\n return {\n ...state,\n index: i,\n selected,\n playing: false,\n commentPlayId: r.mediafile.id,\n commentPlaying: true, //should I have a useEffect like playItem?\n itemPlaying: false,\n rowData: newRows.length > 0 ? newRows : rowData,\n };\n });\n } else {\n setState((state: ICtxState) => {\n return {\n ...state,\n index: i,\n selected,\n playing: false,\n commentPlaying: false,\n playItem: r.mediafile.id,\n itemPlaying: false, //useEffect will turn this on\n rowData: newRows.length > 0 ? newRows : rowData,\n };\n });\n }\n };\n\n const setPlayItem = (playItem: string) => {\n setState((state: ICtxState) => {\n return {\n ...state,\n playItem: playItem,\n };\n });\n };\n\n const setCommentPlayId = (mediaId: string) => {\n setState((state: ICtxState) => {\n return {\n ...state,\n commentPlayId: mediaId,\n };\n });\n };\n\n const oldVernReset = () => {\n mediaStart.current = undefined;\n mediaEnd.current = undefined;\n mediaPosition.current = undefined;\n handleOldVernacularPlayEnd();\n };\n\n const setMediaSelected = (id: string, start: number, end: number) => {\n mediaStart.current = start;\n mediaEnd.current = end;\n setSelected(id, PlayInPlayer.no, state.rowData);\n };\n\n const handleLoaded = () => {\n setState((state: ICtxState) => {\n return {\n ...state,\n oldVernacularPlaying: true,\n };\n });\n };\n\n const setCurrentSegment = (\n segment: IRegion | undefined,\n currentSegmentIndex: number\n ) => {\n if (\n settingSegmentRef.current &&\n ((!segment && highlightRef.current === undefined) ||\n (segment && segment.start === highlightRef.current))\n ) {\n settingSegmentRef.current = false;\n }\n if (!settingSegmentRef.current && segment?.start !== highlightRef.current) {\n handleHighlightDiscussion(undefined);\n settingSegmentRef.current = false;\n }\n if (\n currentSegmentRef.current !== segment ||\n currentSegmentIndexRef.current !== currentSegmentIndex\n ) {\n currentSegmentRef.current = segment;\n currentSegmentIndexRef.current = currentSegmentIndex;\n currentSegmentSeqRef.current += 1;\n setState((state: ICtxState) => ({\n ...state,\n currentSegment: prettySegment(segment),\n currentSegmentIndex,\n currentSegmentSeq: currentSegmentSeqRef.current,\n }));\n }\n };\n const setupLocate = (cb?: (segments: string) => void) => {\n segmentsCb.current = cb;\n };\n //set the player segment to the specified segment??\n const setPlayerSegments = (segments: string) => {\n if (segmentsCb.current) segmentsCb.current(segments);\n settingSegmentRef.current = false;\n };\n\n const getCurrentSegment = () => {\n return currentSegmentRef.current;\n };\n\n const toggleDone = (id: string) => {\n const newRows = state.rowData.map((r) =>\n r.id === id ? { ...r, done: !r.done } : r\n );\n setState((state: ICtxState) => ({ ...state, rowData: newRows }));\n };\n\n const stepCmp = (a: StepComplete, b: StepComplete) =>\n a.stepid > b.stepid ? 1 : -1;\n\n useEffect(() => {\n const passageId =\n remoteIdGuid('passage', pasId ?? '', memory?.keyMap as RecordKeyMap) ||\n pasId ||\n '';\n const p = passages.find((p) => p.id === passageId);\n if (p) {\n const complete = getStepComplete(p).sort(stepCmp);\n const s = sections.find((s) => s.id === related(p, 'section'));\n if (s) {\n if (p.id !== state.passage.id || s.id !== state.section.id) {\n setState((state: ICtxState) => {\n const sharedResource = findRecord(\n memory,\n 'sharedresource',\n related(p, 'sharedResource')\n ) as SharedResourceD;\n return {\n ...state,\n passage: p as PassageD,\n section: s as SectionD,\n sharedResource,\n psgCompleted: [...complete],\n };\n });\n } else {\n const sortedPrev = [...state.psgCompleted].sort(stepCmp);\n const sortedNew = [...complete].sort(stepCmp);\n const sameAsOrbit =\n sortedPrev.length === sortedNew.length &&\n sortedPrev.every((c, i) => shallowEqual(c, sortedNew[i]));\n if (!sameAsOrbit) {\n setState((state: ICtxState) => ({\n ...state,\n psgCompleted: [...complete],\n }));\n }\n }\n }\n }\n // Intentionally omit state.psgCompleted from deps: this effect writes psgCompleted;\n // listing it retriggers every sync and causes \"Maximum update depth exceeded\".\n // eslint-disable-next-line react-hooks/exhaustive-deps -- sync from orbit only; see comment above\n }, [memory, pasId, passages, sections, state.passage.id, state.section.id]);\n\n useEffect(() => {\n if (!booksLoaded) {\n fetchBooks(lang);\n } else {\n setState((state: ICtxState) => {\n return { ...state, allBookData };\n });\n }\n /* eslint-disable-next-line react-hooks/exhaustive-deps */\n }, [lang, booksLoaded, allBookData]);\n\n useEffect(() => {\n if (blobState.blobStat === BlobStatus.FETCHED) {\n setState((state: ICtxState) => {\n return {\n ...state,\n loading: false,\n audioBlob: blobState.blob,\n playing: false,\n };\n });\n fetching.current = '';\n } else if (blobState.blobStat === BlobStatus.ERROR) {\n const errText = blobState?.error || 'Blob loading error';\n if (errText.startsWith('no offline file'))\n showMessage(sharedStr.fileNotFound);\n else showMessage(errText);\n logError(Severity.error, errorReporter, errText);\n setState((state: ICtxState) => {\n return {\n ...state,\n loading: false,\n audioBlob: undefined,\n playing: false,\n };\n });\n fetching.current = '';\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blobState]);\n\n useEffect(() => {\n if (saveResult) {\n logError(Severity.error, errorReporter, saveResult);\n showMessage(saveResult);\n setSaveResult('');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [saveResult]);\n\n useEffect(() => {\n const passageId =\n remoteIdGuid('passage', pasId ?? '', memory?.keyMap as RecordKeyMap) ||\n pasId ||\n '';\n const passRec = passages.find((p) => p.id === passageId);\n let psgId = undefined;\n if (related(passRec, 'sharedResource')) {\n const sr = findRecord(\n memory,\n 'sharedresource',\n related(passRec, 'sharedResource')\n ) as SharedResourceD;\n psgId = related(sr, 'passage');\n }\n const allMedia = getAllMediaRecs(psgId ?? passageId, memory);\n const localize = {\n localizedCategory: localizedArtifactCategory,\n localizedType: localizedArtifactType,\n };\n const pres = getProjectResources();\n let newData = mediaRows({\n artifactTypes,\n categories,\n userResources,\n mediafiles: allMedia.concat(pres) as MediaFileD[],\n user,\n ...localize,\n });\n\n const sectId = related(passRec, 'section');\n const res = getResources(sectionResources, mediafiles, sectId);\n newData = newData.concat(\n resourceRows({\n artifactTypes,\n categories,\n userResources,\n mediafiles,\n res,\n user,\n ...localize,\n }).sort((i, j) => i.sequenceNum - j.sequenceNum)\n );\n\n const mediafileId =\n newData.length > 0 && (newData[0] as IRow).isVernacular\n ? (newData[0] as IRow).id\n : '';\n const i = state.selected\n ? newData.findIndex((r) => r.mediafile.id === state.selected)\n : state.index;\n const willSetSelected =\n state.tool !== ToolSlug.Resource &&\n state.tool !== ToolSlug.Transcribe &&\n mediafileId !== state.playerMediafile?.id;\n setState((state: ICtxState) => {\n return { ...state, rowData: newData, index: i, mediafileId };\n });\n\n if (willSetSelected) {\n setSelected(mediafileId, PlayInPlayer.yes, newData);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [sectionResources, mediafiles, pasId, userResources]);\n\n useEffect(() => {\n let delayedPlay: NodeJS.Timeout | undefined = undefined;\n //if I set playing when I set the mediaId, it plays a bit of the old\n //if not starting at the beginning set to playing after loaded\n if (state.playItem && mediaStart.current === undefined)\n delayedPlay = setTimeout(() => {\n setItemPlaying(true);\n }, 2000);\n\n return () => {\n if (delayedPlay) clearTimeout(delayedPlay);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.playItem]);\n\n useEffect(() => {\n if (state.orgWorkflowSteps !== filteredOrgSteps) {\n setState((state) => ({ ...state, orgWorkflowSteps: filteredOrgSteps }));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [filteredOrgSteps]);\n\n useEffect(() => {\n const wf: SimpleWf[] = state.orgWorkflowSteps.map((s) => ({\n id: s.id,\n label: s.attributes.name,\n }));\n setState((state: ICtxState) => ({ ...state, workflow: wf }));\n }, [state.orgWorkflowSteps]);\n\n useEffect(() => {\n return () => {\n forceClearPending();\n };\n }, []);\n\n useEffect(() => {\n if (state.currentstep === '' && state.orgWorkflowSteps.length > 0) {\n const next = getNextStep(state);\n if (state.currentstep !== next) {\n handleSetCurrentStep(\n next || (state.orgWorkflowSteps[0] as OrgWorkflowStepD).id\n );\n }\n segmentsCb.current = undefined;\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.currentstep, state.psgCompleted, state.orgWorkflowSteps]);\n\n if (view.current !== '') {\n const target = view.current;\n view.current = '';\n return ;\n }\n\n return (\n \n {props.children}\n {/*this is only used to play old vernacular file segments*/}\n \n {confirm !== '' && (\n \n )}\n \n \n );\n};\n\nexport { PassageDetailContext, PassageDetailProvider };\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\PlanContext.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,54],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getProjectDefault'. Either include it or remove the dependency array.","line":128,"column":6,"nodeType":"ArrayExpression","endLine":128,"endColumn":30,"suggestions":[{"desc":"Update the dependencies array to be: [project, defaultParams, getProjectDefault]","fix":{"range":[4621,4645],"text":"[project, defaultParams, getProjectDefault]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'getProjectDefault' and 'setProjectDefault'. Either include them or remove the dependency array.","line":145,"column":5,"nodeType":"ArrayExpression","endLine":145,"endColumn":7,"suggestions":[{"desc":"Update the dependencies array to be: [getProjectDefault, setProjectDefault]","fix":{"range":[5350,5352],"text":"[getProjectDefault, setProjectDefault]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getPlanType'. Either include it or remove the dependency array.","line":157,"column":6,"nodeType":"ArrayExpression","endLine":157,"endColumn":30,"suggestions":[{"desc":"Update the dependencies array to be: [plan, plans, planTypes, getPlanType]","fix":{"range":[5718,5742],"text":"[plan, plans, planTypes, getPlanType]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'isDeveloper', 'isOffline', 'memory', and 'state'. Either include them or remove the dependency array.","line":186,"column":6,"nodeType":"ArrayExpression","endLine":186,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [isDeveloper, isOffline, memory, project, state]","fix":{"range":[6606,6615],"text":"[isDeveloper, isOffline, memory, project, state]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'togglePublishing'. Either include it or remove the dependency array.","line":216,"column":5,"nodeType":"ArrayExpression","endLine":224,"endColumn":6,"suggestions":[{"desc":"Update the dependencies array to be: [state, sectionArr, setSectionArr, connected, canEditSheet, canEditAudio, canPublish, togglePublishing]","fix":{"range":[7362,7496],"text":"[state, sectionArr, setSectionArr, connected, canEditSheet, canEditAudio, canPublish, togglePublishing]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable @typescript-eslint/no-unused-vars */\nimport React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useGlobal } from '../context/useGlobal';\nimport {\n ProjectD,\n DiscussionD,\n MediaFileD,\n GroupMembershipD,\n Plan,\n PlanType,\n} from '../model';\nimport { findRecord, usePlanType } from '../crud';\nimport {\n projDefSectionMap,\n useProjectDefaults,\n} from '../crud/useProjectDefaults';\nimport { useOrbitData } from '../hoc/useOrbitData';\nimport { LocalKey, localUserKey } from '../utils';\nimport { useProjectPermissions } from '../utils/useProjectPermissions';\nimport { SectionArray } from '../model/SectionArray';\nexport interface IRowData {}\n\nconst initState = {\n connected: false,\n mediafiles: [] as MediaFileD[],\n discussions: [] as DiscussionD[],\n groupmemberships: [] as GroupMembershipD[],\n scripture: false,\n flat: false,\n shared: false,\n publishingOn: true,\n hidePublishing: true,\n canEditSheet: false,\n canEditAudio: false,\n canPublish: false,\n sectionArr: [] as SectionArray,\n setSectionArr: (_sectionArr: SectionArray) => {},\n togglePublishing: () => {},\n setCanAddPublishing: (_canAddPublishing: boolean) => {},\n tab: 0,\n setTab: (_tab: number) => {},\n};\n\nexport type ICtxState = typeof initState;\n\ninterface IContext {\n state: ICtxState;\n setState: React.Dispatch>;\n}\n\nconst PlanContext = React.createContext({\n state: initState as ICtxState,\n setState: () => {},\n} as IContext);\n\ninterface IProps {\n children: React.ReactElement;\n}\n\nconst EMPTY_SECTION_ARR: SectionArray = [];\n\nconst PlanProvider = (props: IProps) => {\n const mediafiles = useOrbitData('mediafile');\n const discussions = useOrbitData('discussion');\n const groupmemberships = useOrbitData('groupmembership');\n const projects = useOrbitData('project');\n // Re-read flat/scripture when plan or plantype records arrive (TT-7641).\n // Depending only on plan id left scripture=false until a full remount.\n const plans = useOrbitData('plan');\n const planTypes = useOrbitData('plantype');\n const [memory] = useGlobal('memory');\n const [plan] = useGlobal('plan'); //will be constant here\n const [project] = useGlobal('project'); //will be constant here\n const [connected] = useGlobal('connected'); //verified this is not used in a function 2/18/25\n const [isOffline] = useGlobal('offline'); //verified this is not used in a function 2/18/25\n const [offlineOnly] = useGlobal('offlineOnly');\n const [isDeveloper] = useGlobal('developer');\n const getPlanType = usePlanType();\n const { setProjectDefault, getProjectDefault } = useProjectDefaults();\n const {\n canEditSheet: canEditSheetPerm,\n canEditSheetBase,\n canPublish,\n } = useProjectPermissions();\n const [addStoryOrPassage] = useGlobal('addStoryOrPassage');\n // Bold-workflow members can add sections/passages when the session-only\n // \"Add {Story} or Passage\" flag is set (see UserMenu). The flag can only be\n // set in a bold context, so no extra workflow guard is needed here.\n // Structural sheet edits (adding/moving sections & passages) still require\n // connectivity to the server, same as admins/sheet-editors -- see TT-7521.\n // Audio upload/delete is safe to allow offline (it queues for later sync),\n // so canEditAudio intentionally does not apply that restriction.\n const structuralOffline = isOffline && !offlineOnly;\n const canEditSheet =\n canEditSheetPerm || (addStoryOrPassage && !structuralOffline);\n const canEditAudio = canEditSheetBase || addStoryOrPassage;\n const [state, setState] = useState(() => {\n const { scripture, flat } = getPlanType(plan);\n return {\n ...initState,\n mediafiles,\n discussions,\n groupmemberships,\n scripture,\n flat,\n };\n });\n // Keep sectionArr in React state so consumers see a stable reference between\n // real updates (getProjectDefault JSON-parses a new array every call).\n const [sectionArr, setSectionArrState] =\n useState(EMPTY_SECTION_ARR);\n\n const setTab = (tab: number) => {\n setState((state) => ({ ...state, tab }));\n };\n\n const defaultParams = projects.find((p) => p.id === project)?.attributes\n ?.defaultParams;\n\n useEffect(() => {\n const map = getProjectDefault(projDefSectionMap) as\n SectionArray | undefined;\n const next = map?.length ? map : EMPTY_SECTION_ARR;\n setSectionArrState((prev) =>\n JSON.stringify(prev) === JSON.stringify(next) ? prev : next\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [project, defaultParams]);\n\n const setSectionArr = useCallback(\n (newArr: SectionArray) => {\n const next = newArr.length ? newArr : EMPTY_SECTION_ARR;\n setSectionArrState((prev) => {\n if (JSON.stringify(prev) === JSON.stringify(next)) return prev;\n return next;\n });\n // Persist outside the updater. Empty map stays [] (do not delete the key).\n const prev = getProjectDefault(projDefSectionMap) as\n SectionArray | undefined;\n const prevNorm = prev?.length ? prev : EMPTY_SECTION_ARR;\n if (JSON.stringify(prevNorm) === JSON.stringify(next)) return;\n setProjectDefault(projDefSectionMap, next);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n );\n\n useEffect(() => {\n const { scripture, flat } = getPlanType(plan);\n setState((prev) =>\n flat === prev.flat && scripture === prev.scripture\n ? prev\n : { ...prev, flat, scripture }\n );\n // plans/planTypes: re-run when Orbit has the plan or plantype (Book column).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [plan, plans, planTypes]);\n\n useEffect(() => {\n const projRec = findRecord(memory, 'project', project) as ProjectD;\n if (projRec) {\n const shared = projRec?.attributes?.isPublic || false;\n const hideId = LocalKey.hidePublishing + project;\n const hidePublish =\n localStorage.getItem(localUserKey(hideId as LocalKey)) || 'true';\n const hidePublishing = Boolean(\n hidePublish === 'true' || (isOffline && !isDeveloper)\n );\n\n if (\n shared !== state.shared ||\n hidePublishing !== state[LocalKey.hidePublishing]\n ) {\n setState((state) => ({\n ...state,\n shared,\n hidePublishing,\n }));\n localStorage.setItem(\n localUserKey(hideId as LocalKey),\n hidePublishing.toString()\n );\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [project]);\n\n const setCanAddPublishing = (publishingOn: boolean) => {\n setState((state) => ({ ...state, publishingOn }));\n };\n\n const togglePublishing = () => {\n const { hidePublishing } = state;\n const hideId = LocalKey.hidePublishing + project;\n localStorage.setItem(\n localUserKey(hideId as LocalKey),\n (!hidePublishing).toString()\n );\n setState((state) => ({ ...state, hidePublishing: !hidePublishing }));\n };\n\n const ctxState = useMemo(\n () => ({\n ...state,\n sectionArr,\n setSectionArr,\n connected,\n canEditSheet,\n canEditAudio,\n canPublish,\n togglePublishing,\n setCanAddPublishing,\n setTab,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n state,\n sectionArr,\n setSectionArr,\n connected,\n canEditSheet,\n canEditAudio,\n canPublish,\n ]\n );\n\n return (\n \n {props.children}\n \n );\n};\n\nexport { PlanContext, PlanProvider };\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\PlayInPlayer.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\TeamContext.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'teamId' is defined but never used. Allowed unused args must match /^_/u.","line":101,"column":18,"nodeType":null,"messageId":"unusedVar","endLine":101,"endColumn":24,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'teamId' is defined but never used. Allowed unused args must match /^_/u.","line":102,"column":17,"nodeType":null,"messageId":"unusedVar","endLine":102,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'plan' is defined but never used. Allowed unused args must match /^_/u.","line":103,"column":17,"nodeType":null,"messageId":"unusedVar","endLine":103,"endColumn":21,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'cb' is defined but never used. Allowed unused args must match /^_/u.","line":103,"column":30,"nodeType":null,"messageId":"unusedVar","endLine":103,"endColumn":32,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'project' is defined but never used. Allowed unused args must match /^_/u.","line":104,"column":22,"nodeType":null,"messageId":"unusedVar","endLine":104,"endColumn":29,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'project' is defined but never used. Allowed unused args must match /^_/u.","line":107,"column":17,"nodeType":null,"messageId":"unusedVar","endLine":107,"endColumn":24,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'project' is defined but never used. Allowed unused args must match /^_/u.","line":108,"column":21,"nodeType":null,"messageId":"unusedVar","endLine":108,"endColumn":28,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'project' is defined but never used. Allowed unused args must match /^_/u.","line":109,"column":24,"nodeType":null,"messageId":"unusedVar","endLine":109,"endColumn":31,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'project' is defined but never used. Allowed unused args must match /^_/u.","line":110,"column":21,"nodeType":null,"messageId":"unusedVar","endLine":110,"endColumn":28,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'project' is defined but never used. Allowed unused args must match /^_/u.","line":111,"column":25,"nodeType":null,"messageId":"unusedVar","endLine":111,"endColumn":32,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'team' is defined but never used. Allowed unused args must match /^_/u.","line":111,"column":44,"nodeType":null,"messageId":"unusedVar","endLine":111,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'project' is defined but never used. Allowed unused args must match /^_/u.","line":112,"column":19,"nodeType":null,"messageId":"unusedVar","endLine":112,"endColumn":26,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'project' is defined but never used. Allowed unused args must match /^_/u.","line":113,"column":19,"nodeType":null,"messageId":"unusedVar","endLine":113,"endColumn":26,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'team' is defined but never used. Allowed unused args must match /^_/u.","line":115,"column":5,"nodeType":null,"messageId":"unusedVar","endLine":115,"endColumn":9,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'process' is defined but never used. Allowed unused args must match /^_/u.","line":116,"column":5,"nodeType":null,"messageId":"unusedVar","endLine":116,"endColumn":12,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'cb' is defined but never used. Allowed unused args must match /^_/u.","line":117,"column":5,"nodeType":null,"messageId":"unusedVar","endLine":117,"endColumn":7,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'team' is defined but never used. Allowed unused args must match /^_/u.","line":119,"column":16,"nodeType":null,"messageId":"unusedVar","endLine":119,"endColumn":20,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'team' is defined but never used. Allowed unused args must match /^_/u.","line":120,"column":22,"nodeType":null,"messageId":"unusedVar","endLine":120,"endColumn":26,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'team' is defined but never used. Allowed unused args must match /^_/u.","line":121,"column":13,"nodeType":null,"messageId":"unusedVar","endLine":121,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'team' is defined but never used. Allowed unused args must match /^_/u.","line":122,"column":20,"nodeType":null,"messageId":"unusedVar","endLine":122,"endColumn":24,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'planId' is defined but never used. Allowed unused args must match /^_/u.","line":124,"column":5,"nodeType":null,"messageId":"unusedVar","endLine":124,"endColumn":11,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'mediaRemoteIds' is defined but never used. Allowed unused args must match /^_/u.","line":125,"column":5,"nodeType":null,"messageId":"unusedVar","endLine":125,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'book' is defined but never used. Allowed unused args must match /^_/u.","line":126,"column":5,"nodeType":null,"messageId":"unusedVar","endLine":126,"endColumn":9,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'setComplete' is defined but never used. Allowed unused args must match /^_/u.","line":127,"column":5,"nodeType":null,"messageId":"unusedVar","endLine":127,"endColumn":16,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'val' is defined but never used. Allowed unused args must match /^_/u.","line":130,"column":19,"nodeType":null,"messageId":"unusedVar","endLine":130,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'p' is assigned a value but never used. Allowed unused args must match /^_/u.","line":132,"column":14,"nodeType":null,"messageId":"unusedVar","endLine":132,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'team' is defined but never used. Allowed unused args must match /^_/u.","line":133,"column":35,"nodeType":null,"messageId":"unusedVar","endLine":133,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'team' is defined but never used. Allowed unused args must match /^_/u.","line":134,"column":17,"nodeType":null,"messageId":"unusedVar","endLine":134,"endColumn":21,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'arr' is defined but never used. Allowed unused args must match /^_/u.","line":135,"column":30,"nodeType":null,"messageId":"unusedVar","endLine":135,"endColumn":33,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'projects' is defined but never used. Allowed unused args must match /^_/u.","line":136,"column":25,"nodeType":null,"messageId":"unusedVar","endLine":136,"endColumn":33,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'tab' is defined but never used. Allowed unused args must match /^_/u.","line":138,"column":12,"nodeType":null,"messageId":"unusedVar","endLine":138,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'fetchBooks'. Either include it or remove the dependency array.","line":619,"column":6,"nodeType":"ArrayExpression","endLine":619,"endColumn":25,"suggestions":[{"desc":"Update the dependencies array to be: [lang, allBookData, fetchBooks]","fix":{"range":[19730,19749],"text":"[lang, allBookData, fetchBooks]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getSortMap', 'oProjRead', 'planSort', and 'vProject'. Either include them or remove the dependency array.","line":641,"column":6,"nodeType":"ArrayExpression","endLine":641,"endColumn":73,"suggestions":[{"desc":"Update the dependencies array to be: [userProjects, organizations, plans, isOffline, state.personalTeam, getSortMap, planSort, oProjRead, vProject]","fix":{"range":[20435,20502],"text":"[userProjects, organizations, plans, isOffline, state.personalTeam, getSortMap, planSort, oProjRead, vProject]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getTeamId', 'getTeams', 'state.personalTeam', and 'state.teams'. Either include them or remove the dependency array.","line":666,"column":6,"nodeType":"ArrayExpression","endLine":666,"endColumn":50,"suggestions":[{"desc":"Update the dependencies array to be: [organizations, orgMembers, user, isOffline, state.personalTeam, state.teams, getTeams, getTeamId]","fix":{"range":[21410,21454],"text":"[organizations, orgMembers, user, isOffline, state.personalTeam, state.teams, getTeams, getTeamId]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\TokenProvider.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'getAccessTokenSilently', 'handleLogOut', 'loginWithRedirect', 'options', 'setAuthSession', and 'webTokenOptions'. Either include them or remove the dependency array.","line":130,"column":6,"nodeType":"ArrayExpression","endLine":130,"endColumn":29,"suggestions":[{"desc":"Update the dependencies array to be: [getAccessTokenSilently, handleLogOut, isAuthenticated, loginWithRedirect, options, setAuthSession, user, webTokenOptions]","fix":{"range":[4166,4189],"text":"[getAccessTokenSilently, handleLogOut, isAuthenticated, loginWithRedirect, options, setAuthSession, user, webTokenOptions]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'getGlobal' and 'resetExpiresAt'. Either include them or remove the dependency array.","line":215,"column":6,"nodeType":"ArrayExpression","endLine":215,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [getGlobal, resetExpiresAt]","fix":{"range":[7163,7165],"text":"[getGlobal, resetExpiresAt]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'handleLogOut'. Either include it or remove the dependency array.","line":289,"column":6,"nodeType":"ArrayExpression","endLine":289,"endColumn":34,"suggestions":[{"desc":"Update the dependencies array to be: [handleLogOut, modalOpen, secondsToExpire]","fix":{"range":[9355,9383],"text":"[handleLogOut, modalOpen, secondsToExpire]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\TranscriberContext.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,54],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'mediaPassageIdFromRoute'. Either include it or remove the dependency array.","line":206,"column":6,"nodeType":"ArrayExpression","endLine":206,"endColumn":73,"suggestions":[{"desc":"Update the dependencies array to be: [mediafiles, devPlan, artifactId, stepLanguageBcp47, pasId, memory, mediaPassageIdFromRoute]","fix":{"range":[6375,6442],"text":"[mediafiles, devPlan, artifactId, stepLanguageBcp47, pasId, memory, mediaPassageIdFromRoute]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'addTasks', 'curRole', 'isDetail', 'mediaPassageIdFromRoute', 'memory?.keyMap', 'selectTasks', 'setTransSelected', 'state.allDone', 'state.playItem', and 'state.transSelected'. Either include them or remove the dependency array.","line":522,"column":6,"nodeType":"ArrayExpression","endLine":522,"endColumn":51,"suggestions":[{"desc":"Update the dependencies array to be: [planMedia, refreshed, pasId, medId, planRec, state.playItem, state.allDone, state.transSelected, selectTasks, isDetail, addTasks, mediaPassageIdFromRoute, memory?.keyMap, curRole, setTransSelected]","fix":{"range":[15213,15258],"text":"[planMedia, refreshed, pasId, medId, planRec, state.playItem, state.allDone, state.transSelected, selectTasks, isDetail, addTasks, mediaPassageIdFromRoute, memory?.keyMap, curRole, setTransSelected]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'actor' and 'state'. Either include them or remove the dependency array. You can also do a functional update 'setState(s => ...)' if you only need 'state' in the 'setState' call.","line":562,"column":6,"nodeType":"ArrayExpression","endLine":562,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [actor, sections, state]","fix":{"range":[16627,16637],"text":"[actor, sections, state]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'actor', 'curRole', 'isDetail', 'noNewSelection', and 'state'. Either include them or remove the dependency array. You can also do a functional update 'setState(s => ...)' if you only need 'state' in the 'setState' call.","line":613,"column":6,"nodeType":"ArrayExpression","endLine":613,"endColumn":25,"suggestions":[{"desc":"Update the dependencies array to be: [actor, curRole, isDetail, mediafiles, noNewSelection, pasId, state]","fix":{"range":[18228,18247],"text":"[actor, curRole, isDetail, mediafiles, noNewSelection, pasId, state]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'fetchBooks'. Either include it or remove the dependency array.","line":624,"column":6,"nodeType":"ArrayExpression","endLine":624,"endColumn":38,"suggestions":[{"desc":"Update the dependencies array to be: [lang, booksLoaded, allBookData, fetchBooks]","fix":{"range":[18497,18529],"text":"[lang, booksLoaded, allBookData, fetchBooks]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'getPlan' and 'state.flat'. Either include them or remove the dependency array.","line":645,"column":6,"nodeType":"ArrayExpression","endLine":645,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [devPlan, getPlan, state.flat]","fix":{"range":[19049,19058],"text":"[devPlan, getPlan, state.flat]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable @typescript-eslint/no-unused-vars */\nimport React, { useState, useEffect, useRef, useMemo, useContext } from 'react';\n// see: https://upmostly.com/tutorials/how-to-use-the-usecontext-hook-in-react\nimport { useGlobal } from '../context/useGlobal';\nimport { useParams } from 'react-router-dom';\nimport * as actions from '../store';\nimport {\n IState,\n Passage,\n PassageD,\n Plan,\n PlanTypeD,\n Section,\n SectionD,\n MediaFile,\n MediaFileD,\n BookName,\n ActivityStates,\n} from '../model';\nimport {\n related,\n sectionNumber,\n taskPassageNumber,\n remoteIdGuid,\n usePlan,\n useArtifactType,\n getMediaInPlans,\n findRecord,\n VernacularTag,\n mediaPassageIdForTranscribe,\n filterMediaForPassage,\n transcribeMediaForPassage,\n} from '../crud';\nimport { mediaFileName } from '../crud/media';\nimport { mediaMatchesStepLanguage } from '../utils/mediaLanguage';\nimport StickyRedirect from '../components/StickyRedirect';\nimport { useSelector } from 'react-redux';\nimport { useDispatch } from 'react-redux';\nimport { InitializedRecord, RecordKeyMap } from '@orbit/records';\nimport { useOrbitData } from '../hoc/useOrbitData';\nimport { PassageDetailContext } from './PassageDetailContext';\n\nexport interface IRowData {\n planName: string;\n planType: string;\n section: SectionD;\n passage: PassageD;\n mediafile: MediaFileD;\n state: string;\n sectPass: string;\n playItem: string;\n duration: number;\n role: string;\n assigned: string;\n transcriber: string;\n editor: string;\n}\n\nfunction sourceSegmentStart(mediafile: MediaFileD): number {\n const seg = mediafile.attributes?.sourceSegments;\n if (!seg) return Number.NaN;\n try {\n return parseFloat(JSON.parse(seg as string).start);\n } catch {\n return Number.NaN;\n }\n}\n\nfunction compareTranscribeRowsByPhrase(a: IRowData, b: IRowData): number {\n const aStart = sourceSegmentStart(a.mediafile);\n const bStart = sourceSegmentStart(b.mediafile);\n if (!Number.isNaN(aStart) && !Number.isNaN(bStart)) return aStart - bStart;\n if (!Number.isNaN(aStart)) return -1;\n if (!Number.isNaN(bStart)) return 1;\n return mediaFileName(a.mediafile) <= mediaFileName(b.mediafile) ? -1 : 1;\n}\n\n/** First passage-detail transcriber task in phrase order (PBT segments). */\nfunction firstPassageTranscriberTaskId(\n rowList: IRowData[],\n passageOrbitId: string\n): string | undefined {\n const candidates = rowList.filter(\n (r) =>\n r.passage?.id === passageOrbitId &&\n r.mediafile?.id &&\n r.role === 'transcriber'\n );\n if (candidates.length === 0) return undefined;\n candidates.sort(compareTranscribeRowsByPhrase);\n return candidates[0].mediafile.id as string;\n}\n\nfunction firstRealTaskMediaId(rowList: IRowData[]): string | undefined {\n const row = rowList.find((r) => r.passage?.id && r.mediafile?.id);\n return row?.mediafile.id as string | undefined;\n}\n\nconst initState = {\n transSelected: undefined as string | undefined, //mediafileid\n setTransSelected: (\n _selected: string | undefined,\n _rowData?: IRowData[]\n ) => {},\n index: -1,\n rowData: Array(),\n expandedGroups: Array(),\n playItem: '',\n allDone: false,\n setAllDone: (_val: boolean) => {},\n refresh: () => {},\n allBookData: Array(),\n flat: false,\n artifactId: null as string | null,\n isDetail: false,\n};\n\nexport type ICtxState = typeof initState;\n\ninterface IContext {\n state: ICtxState;\n setState: React.Dispatch>;\n}\n\nconst TranscriberContext = React.createContext({\n state: initState as ICtxState,\n setState: () => {},\n} as IContext);\n\ninterface IProps {\n children: React.ReactElement;\n artifactTypeId?: string | null | undefined;\n curRole?: string;\n /** Step language. When set (and not `und`), only media tagged with it become tasks. */\n stepLanguageBcp47?: string;\n}\nconst TranscriberProvider = (props: IProps) => {\n const { artifactTypeId, curRole, stepLanguageBcp47 } = props;\n const [isDetail] = useState(artifactTypeId !== undefined);\n const passages = useOrbitData('passage');\n const sections = useOrbitData('section');\n const mediafiles = useOrbitData('mediafile');\n const allBookData = useSelector((state: IState) => state.books.bookData);\n const lang = useSelector((state: IState) => state.strings.lang);\n const booksLoaded = useSelector((state: IState) => state.books.loaded);\n const dispatch = useDispatch();\n const fetchBooks = (lang: string) =>\n dispatch(actions.fetchBooks(lang) as any);\n const { pasId, slug, medId } = useParams();\n const [memory] = useGlobal('memory');\n const [user] = useGlobal('user');\n const [devPlan] = useGlobal('plan'); //will be constant here\n const { getPlan, getPlanRecName } = usePlan();\n const view = React.useRef('');\n const [refreshed, setRefreshed] = useState(0);\n const [planMedia, setPlanMedia] = useState([]);\n const planMediaRef = useRef([]);\n const passageMediaRef = useRef([]);\n const [planRec, setPlanRec] = useState({} as Plan);\n const { sectionArr } = useContext(PassageDetailContext).state;\n const sectionMap = new Map(sectionArr);\n const [state, setState] = useState({\n ...initState,\n allBookData,\n isDetail,\n });\n const { getTypeId } = useArtifactType();\n\n const artifactId = useMemo(\n () => (slug ? getTypeId(slug) : (artifactTypeId ?? VernacularTag)),\n [slug, artifactTypeId, getTypeId]\n );\n\n const mediaPassageIdFromRoute = (routePasId?: string) => {\n const psg =\n remoteIdGuid(\n 'passage',\n routePasId ?? '',\n memory?.keyMap as RecordKeyMap\n ) ||\n routePasId ||\n '';\n const passRec = findRecord(memory, 'passage', psg) as PassageD | undefined;\n return mediaPassageIdForTranscribe(passRec, memory) || psg;\n };\n\n useEffect(() => {\n if (mediafiles.length === 0) return;\n let m: MediaFileD[] = [];\n if (pasId) {\n m = transcribeMediaForPassage(\n mediafiles,\n mediaPassageIdFromRoute(pasId),\n artifactId,\n true\n );\n } else if (devPlan) {\n m = getMediaInPlans([devPlan], mediafiles, artifactId, true);\n } else {\n return;\n }\n m = m.filter((mf) => mediaMatchesStepLanguage(mf, stepLanguageBcp47));\n setPlanMedia(m);\n planMediaRef.current = m;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [mediafiles, devPlan, artifactId, stepLanguageBcp47, pasId, memory]);\n\n const setRows = (rowData: IRowData[]) => {\n setState((state: ICtxState) => {\n return { ...state, rowData };\n });\n };\n\n const setExpandedGroups = (expandedGroups: string[]) => {\n setState((state: ICtxState) => {\n return { ...state, expandedGroups };\n });\n };\n\n const setAllDone = (val: boolean) => {\n setState((state: ICtxState) => {\n return { ...state, allDone: val };\n });\n };\n\n const setTransSelected = (\n transSelected: string | undefined,\n rowData: IRowData[] = state.rowData\n ) => {\n let i = -1;\n if (transSelected) {\n if (isDetail && curRole === 'transcriber') {\n i = rowData.findIndex(\n (r) => r.mediafile.id === transSelected && r.role === 'transcriber'\n );\n }\n if (i < 0) {\n i = rowData.findIndex((r) => r.mediafile.id === transSelected);\n }\n }\n if (i < 0) return;\n const r = rowData[i] as IRowData;\n\n if (state.index !== i || state.transSelected !== transSelected) {\n setState((state: ICtxState) => {\n return {\n ...state,\n index: i,\n transSelected,\n playItem: r.mediafile.id,\n };\n });\n }\n };\n\n const refresh = () => {\n setRefreshed((refreshed) => {\n return refreshed + 1;\n });\n };\n\n const getPlanType = (planRec: Plan) => {\n const planType = findRecord(\n memory,\n 'plantype',\n related(planRec, 'plantype')\n ) as PlanTypeD;\n return planType?.attributes.name || '';\n };\n\n const addTasks = (\n state: string,\n role: string,\n rowList: IRowData[],\n onlyAvailable: boolean,\n playItem: string\n ) => {\n if (curRole && curRole !== role && role !== 'view') return;\n const planName = getPlanRecName(planRec);\n const planType = getPlanType(planRec);\n\n const mediaRecs = passageMediaRef.current.filter(\n (m) =>\n role === 'view' ||\n (m.attributes?.transcriptionstate || ActivityStates.TranscribeReady) ===\n state\n );\n const passIds = mediaRecs.map((m) => related(m, 'passage') as string);\n const readyRecs = passages\n .filter((p) => passIds.findIndex((pid) => pid === p.id) >= 0)\n .sort((a, b) =>\n related(a, 'section') <= related(b, 'section') ? -1 : 1\n );\n const addRows = Array();\n let assigned = '';\n let allowed = false;\n let secNum = '';\n let secRec = {} as Section;\n let transcriber = '';\n let editor = '';\n let curSec = '';\n readyRecs.forEach((p) => {\n const passageMediaRecs = mediaRecs\n .filter((m) => related(m, 'passage') === p.id)\n .sort((i: MediaFile, j: MediaFile) =>\n // Sort ascending--vernacular will only have the latest. All others sort by date created (possible upgrade would be segment start if available)\n j.attributes.dateCreated <= i.attributes.dateCreated ? -1 : 1\n );\n\n if (related(p, 'section') !== curSec) {\n curSec = related(p, 'section');\n secRec = findRecord(\n memory,\n 'section',\n related(p, 'section')\n ) as Section;\n if (secRec) {\n secNum = sectionNumber(secRec, sectionMap);\n assigned = ''; // previously controlled: related(secRec, role);\n transcriber = related(secRec, 'transcriber');\n editor = related(secRec, 'editor');\n allowed = onlyAvailable\n ? assigned === user || !assigned || assigned === ''\n : role === 'view';\n\n if (allowed && !rowList.find((r) => r.sectPass === secNum + '.'))\n addRows.push({\n planName,\n planType,\n section: { ...secRec } as SectionD,\n passage: {} as PassageD,\n state: '',\n sectPass: secNum + '.',\n mediafile: {} as MediaFileD,\n playItem: '',\n duration: 0,\n role,\n assigned,\n transcriber,\n editor,\n });\n }\n }\n if (allowed)\n passageMediaRecs.forEach((mediaRec) => {\n let already: IRowData[] = [];\n if (role === 'view') {\n already = rowList.filter((r) => r.mediafile.id === mediaRec.id);\n }\n if (role !== 'view' || already.length === 0) {\n const curState: ActivityStates | string =\n role === 'view'\n ? mediaRec.attributes?.transcriptionstate || state\n : state;\n addRows.push({\n planName,\n planType,\n section: { ...secRec } as SectionD,\n passage: { ...p } as PassageD,\n state: curState,\n sectPass: secNum + '.' + taskPassageNumber(p).trim(),\n mediafile: mediaRec as MediaFileD,\n playItem,\n duration: mediaRec.attributes.duration,\n role,\n assigned,\n transcriber,\n editor,\n });\n }\n });\n });\n addRows\n .sort((i, j) =>\n i.planName < j.planName\n ? -1\n : i.planName > j.planName\n ? 1\n : i.sectPass <= j.sectPass\n ? -1\n : 1\n )\n .forEach((r) => {\n rowList.push(r);\n });\n };\n\n const selectTasks = (\n onlyAvailable: boolean,\n rowList: IRowData[],\n item: string\n ) => {\n // IN PROGRESS TASKS\n addTasks(ActivityStates.Reviewing, 'editor', rowList, onlyAvailable, item);\n\n addTasks(\n ActivityStates.Transcribing,\n 'transcriber',\n rowList,\n onlyAvailable,\n item\n );\n\n // IN PROGRESS BUT ERROR REPORTED\n addTasks(\n ActivityStates.Incomplete,\n 'transcriber',\n rowList,\n onlyAvailable,\n item\n );\n\n addTasks(\n ActivityStates.NeedsNewTranscription,\n 'transcriber',\n rowList,\n onlyAvailable,\n item\n );\n\n // READY TO BEGIN TASKS\n addTasks(\n ActivityStates.Transcribed,\n 'editor',\n rowList,\n onlyAvailable,\n item\n );\n\n addTasks(\n ActivityStates.TranscribeReady,\n 'transcriber',\n rowList,\n onlyAvailable,\n item\n );\n };\n\n useEffect(() => {\n const playItem = state.playItem;\n const rowList: IRowData[] = [];\n if (pasId) {\n passageMediaRef.current = filterMediaForPassage(\n planMediaRef.current,\n mediaPassageIdFromRoute(pasId)\n );\n } else passageMediaRef.current = planMediaRef.current;\n\n selectTasks(true, rowList, playItem); // assigned\n selectTasks(false, rowList, playItem); // unassigned\n const newAllDone = rowList.length === 0 && !isDetail;\n if (newAllDone !== state.allDone) setAllDone(newAllDone);\n // ALL OTHERS\n addTasks('', 'view', rowList, false, playItem);\n\n setRows(rowList.map((r) => r));\n const exGrp: string[] = [];\n rowList.forEach((r) => {\n if (!exGrp.includes(r.planName)) exGrp.push(r.planName);\n });\n setExpandedGroups(exGrp);\n if (rowList.length > 0) {\n let transSelected = state.transSelected;\n if (!transSelected) {\n let mediaId = medId;\n if (!mediaId) {\n //vernacular so should just be one\n const mediaPsg = mediaPassageIdFromRoute(pasId);\n const p = rowList.filter((r) => r.passage.id === mediaPsg);\n if (p.length > 0) mediaId = (p[0] as IRowData).mediafile.id;\n }\n transSelected =\n remoteIdGuid(\n 'mediafile',\n mediaId || '',\n memory?.keyMap as RecordKeyMap\n ) ||\n mediaId ||\n '';\n }\n\n if (transSelected !== '') {\n const rowsForId = rowList.filter(\n (r) => r.mediafile.id === transSelected\n );\n if (rowsForId.length === 0) {\n transSelected = '';\n } else if (\n isDetail &&\n curRole === 'transcriber' &&\n !rowsForId.some((r) => r.role === 'transcriber')\n ) {\n transSelected = '';\n } else {\n setTransSelected(transSelected, rowList);\n }\n }\n if (transSelected === '') {\n const mediaPsg = mediaPassageIdFromRoute(pasId);\n let pick: string | undefined;\n if (isDetail && curRole === 'transcriber' && mediaPsg) {\n pick = firstPassageTranscriberTaskId(rowList, mediaPsg);\n }\n if (!pick) {\n pick = firstRealTaskMediaId(rowList);\n }\n if (pick) {\n setTransSelected(pick, rowList);\n }\n }\n } else {\n setState((state: ICtxState) => {\n return {\n ...state,\n index: -1,\n transSelected: '',\n playItem: '',\n };\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [planMedia, refreshed, pasId, medId, planRec]);\n\n const actor: { [key: string]: string } = {\n [ActivityStates.TranscribeReady]: 'transcriber',\n [ActivityStates.Reviewing]: 'editor',\n [ActivityStates.Transcribing]: 'transcriber',\n [ActivityStates.Transcribed]: 'editor',\n [ActivityStates.Incomplete]: 'transcriber',\n [ActivityStates.NeedsNewTranscription]: 'transcriber',\n '': 'view',\n };\n\n useEffect(() => {\n let changed = false;\n const rowData: IRowData[] = [];\n state.rowData.forEach((r) => {\n const secRecs = sections.filter((s) => s.id === r.section.id);\n if (secRecs.length > 0) {\n const section = { ...secRecs[0] } as SectionD;\n const transcriber = related(section, 'transcriber');\n if (transcriber !== r.transcriber) changed = true;\n const editor = related(section, 'editor');\n if (editor !== r.editor) changed = true;\n const state =\n r.mediafile.attributes?.transcriptionstate ||\n ActivityStates.TranscribeReady;\n const rowRole = actor[state] || 'view';\n const assigned = related(section, rowRole);\n rowData.push({\n ...r,\n section,\n role: rowRole,\n assigned,\n transcriber,\n editor,\n });\n }\n });\n if (changed) setState({ ...state, rowData });\n /* eslint-disable-next-line react-hooks/exhaustive-deps */\n }, [sections]);\n\n const noNewSelection: string[] = [\n ActivityStates.TranscribeReady,\n ActivityStates.Transcribing,\n ActivityStates.Reviewing,\n ];\n\n useEffect(() => {\n let changed = false;\n const rowData: IRowData[] = [];\n let forcerefresh = false;\n state.rowData.forEach((r) => {\n //section\n if (!r.passage.id) rowData.push({ ...r });\n else {\n const mediaRecs = mediafiles.filter((m) => m.id === r.mediafile.id);\n if (mediaRecs.length > 0) {\n const mediafile = { ...mediaRecs[0] } as MediaFile &\n InitializedRecord;\n let role = r.role;\n const newState = mediafile?.attributes?.transcriptionstate;\n if (newState !== r.mediafile?.attributes?.transcriptionstate) {\n changed = true;\n role = actor[newState] || 'view';\n forcerefresh =\n forcerefresh ||\n noNewSelection.indexOf(newState) === -1 ||\n role !== r.role;\n }\n rowData.push({ ...r, mediafile, role });\n }\n }\n });\n if (changed) {\n setState({ ...state, rowData }); //eh...what to do about: playing:false\n if (forcerefresh) {\n refresh(); //force the transcriber pane to refresh also\n } else if (\n isDetail &&\n curRole === 'transcriber' &&\n state.transSelected &&\n !rowData.some(\n (r) =>\n r.mediafile.id === state.transSelected && r.role === 'transcriber'\n )\n ) {\n refresh();\n }\n }\n /* eslint-disable-next-line react-hooks/exhaustive-deps */\n }, [mediafiles, pasId]);\n\n useEffect(() => {\n if (!booksLoaded) {\n fetchBooks(lang);\n } else {\n setState((state: ICtxState) => {\n return { ...state, allBookData };\n });\n }\n /* eslint-disable-next-line react-hooks/exhaustive-deps */\n }, [lang, booksLoaded, allBookData]);\n\n const isFlat = (planRec: Plan) => {\n if (planRec !== null) return planRec.attributes?.flat;\n return false;\n };\n\n React.useEffect(() => {\n if (devPlan !== '') {\n const planRec = getPlan(devPlan);\n if (planRec) {\n setPlanRec(planRec);\n const newFlat = isFlat(planRec);\n if (state.flat !== newFlat)\n setState((state) => ({\n ...state,\n flat: newFlat,\n }));\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [devPlan]);\n\n if (view.current !== '') {\n const target = view.current;\n view.current = '';\n return ;\n }\n\n return (\n \n {props.children}\n \n );\n};\n\nexport { TranscriberContext, TranscriberProvider };\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\UnsavedContext.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'method' is defined but never used. Allowed unused args must match /^_/u.","line":24,"column":18,"nodeType":null,"messageId":"unusedVar","endLine":24,"endColumn":24,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'toolId' is defined but never used. Allowed unused args must match /^_/u.","line":29,"column":17,"nodeType":null,"messageId":"unusedVar","endLine":29,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'changed' is defined but never used. Allowed unused args must match /^_/u.","line":29,"column":33,"nodeType":null,"messageId":"unusedVar","endLine":29,"endColumn":40,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'toolErr' is defined but never used. Allowed unused args must match /^_/u.","line":29,"column":52,"nodeType":null,"messageId":"unusedVar","endLine":29,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'toolId' is defined but never used. Allowed unused args must match /^_/u.","line":30,"column":15,"nodeType":null,"messageId":"unusedVar","endLine":30,"endColumn":21,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'tooldId' is defined but never used. Allowed unused args must match /^_/u.","line":31,"column":16,"nodeType":null,"messageId":"unusedVar","endLine":31,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'toolId' is defined but never used. Allowed unused args must match /^_/u.","line":32,"column":19,"nodeType":null,"messageId":"unusedVar","endLine":32,"endColumn":25,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'saveErr' is defined but never used. Allowed unused args must match /^_/u.","line":32,"column":35,"nodeType":null,"messageId":"unusedVar","endLine":32,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'toolId' is defined but never used. Allowed unused args must match /^_/u.","line":33,"column":20,"nodeType":null,"messageId":"unusedVar","endLine":33,"endColumn":26,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'resolvedMethod' is defined but never used. Allowed unused args must match /^_/u.","line":35,"column":5,"nodeType":null,"messageId":"unusedVar","endLine":35,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'waitCount' is defined but never used. Allowed unused args must match /^_/u.","line":36,"column":5,"nodeType":null,"messageId":"unusedVar","endLine":36,"endColumn":14,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'butMyTooId' is defined but never used. Allowed unused args must match /^_/u.","line":40,"column":15,"nodeType":null,"messageId":"unusedVar","endLine":40,"endColumn":25,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'toolId' is defined but never used. Allowed unused args must match /^_/u.","line":41,"column":19,"nodeType":null,"messageId":"unusedVar","endLine":41,"endColumn":25,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'toolId' is defined but never used. Allowed unused args must match /^_/u.","line":42,"column":20,"nodeType":null,"messageId":"unusedVar","endLine":42,"endColumn":26,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'toolId' is defined but never used. Allowed unused args must match /^_/u.","line":43,"column":15,"nodeType":null,"messageId":"unusedVar","endLine":43,"endColumn":21,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'err' is defined but never used. Allowed unused args must match /^_/u.","line":269,"column":15,"nodeType":null,"messageId":"unusedVar","endLine":269,"endColumn":18,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'err' is defined but never used. Allowed unused args must match /^_/u.","line":297,"column":17,"nodeType":null,"messageId":"unusedVar","endLine":297,"endColumn":20,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\passageDetailNavigationBlocked.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\passageDetailNavigationBlocked.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\useGlobal.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\usePassageDetailContext.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\context\\useTodo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\ActionRow.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\ActionToggle.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\AddSectionPassageButtons.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\AllotmentWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\ApmLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\AudacityLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\BookCombobox.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\BurritoLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\Button.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\CheckedChoice.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\ChoiceHead.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\CommentBox.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\ConfButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\DragHandle.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\Duration.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\GroupOrUserAssignment.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\GrowingDiv.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\GrowingSpacer.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\Guidance.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\IconMenu.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\IosSlider.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\Language.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":42,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":42,"endColumn":13,"suppressions":[{"kind":"directive","justification":"JSX needs React in scope for TS"}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\Language.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\LastEdit.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\LaunchLink.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'doLink'. Either include it or remove the dependency array.","line":42,"column":6,"nodeType":"ArrayExpression","endLine":42,"endColumn":11,"suggestions":[{"desc":"Update the dependencies array to be: [doLink, url]","fix":{"range":[1272,1277],"text":"[doLink, url]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\LightTooltip.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\LinkEdit.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'setDefaultValue'. Either include it or remove the dependency array.","line":35,"column":44,"nodeType":"ArrayExpression","endLine":35,"endColumn":53,"suggestions":[{"desc":"Update the dependencies array to be: [inValue, setDefaultValue]","fix":{"range":[1196,1205],"text":"[inValue, setDefaultValue]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\ListMode.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\LogoImg.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\MarkDownEdit.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":39,"column":5,"severity":1,"nodeType":null,"fix":{"range":[1215,1270],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import {\n Box,\n FormControl,\n FormLabel,\n IconButton,\n Stack,\n TextField,\n} from '@mui/material';\nimport InfoIcon from '@mui/icons-material/Info';\nimport { LightTooltip } from './LightTooltip';\nimport { useEffect, useState } from 'react';\nimport { IMediaUploadStrings, IState } from '../model';\nimport { shallowEqual, useSelector } from 'react-redux';\nimport { mediaUploadSelector } from '../selector';\nimport { LaunchLink } from './LaunchLink';\nimport { MarkDownView } from './MarkDownView';\n\nconst gfmSyntax =\n 'https://docs.github.com/{0}/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax';\n\ninterface MarkDownEditProps {\n inValue?: string;\n onValue?: (value: string) => void;\n wrapPreviewOverflow?: boolean;\n}\n\nexport const MarkDownEdit = ({\n inValue,\n onValue,\n wrapPreviewOverflow = false,\n}: MarkDownEditProps) => {\n const [value, setValue] = useState(inValue || '');\n const [link, setLink] = useState();\n const lang = useSelector((state: IState) => state.strings.lang);\n const t: IMediaUploadStrings = useSelector(mediaUploadSelector, shallowEqual);\n\n useEffect(() => {\n setValue(inValue || '');\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [inValue]);\n\n const handleValue = (e: React.ChangeEvent) => {\n const newValue = e.target.value;\n setValue(newValue);\n onValue && onValue(newValue);\n };\n\n return (\n \n \n {value && (\n \n \n \n {t.preview}\n \n setLink(gfmSyntax.replace('{0}', lang))}\n sx={{ p: '2px' }}\n >\n \n \n \n \n \n \n \n \n \n )}\n setLink('')} />\n \n );\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\MarkDownView.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":28,"column":5,"severity":1,"nodeType":null,"fix":{"range":[854,909],"text":" "}},{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":87,"column":5,"severity":1,"nodeType":null,"fix":{"range":[2472,2527],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":2,"source":"import React from 'react';\nimport MarkDown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { Box } from '@mui/material';\nimport { MainAPI } from '@model/main-api';\nconst ipc = window?.api as MainAPI;\n\ninterface MarkDownProps {\n value: string;\n wrapOverflow?: boolean;\n}\n\nexport function MarkDownView({ value, wrapOverflow = false }: MarkDownProps) {\n // adapted from https://stackoverflow.com/questions/31749625/make-a-link-from-electron-open-in-browser (zrbecker's)\n const handleClick = (event: any) => {\n if (event.target.tagName.toLowerCase() === 'a') {\n event.preventDefault();\n ipc?.openExternal(event.target.href);\n }\n };\n\n React.useEffect(() => {\n if (ipc) document.addEventListener('click', handleClick);\n\n return () => {\n if (ipc) document.removeEventListener('click', handleClick);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n \n {value}\n \n );\n}\n\nexport function CompactMarkDownView({\n value,\n wrapOverflow = false,\n}: MarkDownProps) {\n // adapted from https://stackoverflow.com/questions/31749625/make-a-link-from-electron-open-in-browser (zrbecker's)\n const handleClick = (event: any) => {\n if (event.target.tagName.toLowerCase() === 'a') {\n event.preventDefault();\n ipc?.openExternal(event.target.href);\n }\n };\n\n React.useEffect(() => {\n if (ipc) document.addEventListener('click', handleClick);\n\n return () => {\n if (ipc) document.removeEventListener('click', handleClick);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n \n {value}\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\MediaDescription.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\MediaTitle.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'clearCompleted', 'clearRequested', 'handleOk', 'reset', 'saveCompleted', 'saveRequested', and 'toolId'. Either include them or remove the dependency array.","line":221,"column":6,"nodeType":"ArrayExpression","endLine":221,"endColumn":38,"suggestions":[{"desc":"Update the dependencies array to be: [toolsChanged, canSaveRecording, saveRequested, toolId, clearRequested, handleOk, saveCompleted, reset, clearCompleted]","fix":{"range":[6145,6177],"text":"[toolsChanged, canSaveRecording, saveRequested, toolId, clearRequested, handleOk, saveCompleted, reset, clearCompleted]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setLanguageTitle'. Either include it or remove the dependency array.","line":242,"column":6,"nodeType":"ArrayExpression","endLine":242,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [language, setLanguageTitle]","fix":{"range":[6769,6779],"text":"[language, setLanguageTitle]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'playing'. Either include it or remove the dependency array.","line":371,"column":6,"nodeType":"ArrayExpression","endLine":371,"endColumn":31,"suggestions":[{"desc":"Update the dependencies array to be: [playingMediaId, mediaId, playing]","fix":{"range":[10140,10165],"text":"[playingMediaId, mediaId, playing]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'handleBlur', 'handlePlay', 'handleRecord', 'handleTextChange', 'label', 'language', 'onRecording', and 'required'. Either include them or remove the dependency array.","line":436,"column":5,"nodeType":"ArrayExpression","endLine":446,"endColumn":6,"suggestions":[{"desc":"Update the dependencies array to be: [titlekey, label, curText, language, handleTextChange, handleBlur, helperText, disabled, required, mediaId, handlePlay, recording, playing, handleRecord, onRecording]","fix":{"range":[11863,12019],"text":"[titlekey, label, curText, language, handleTextChange, handleBlur, helperText, disabled, required, mediaId, handlePlay, recording, playing, handleRecord, onRecording]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\NoChickenIcon.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\NormalizeIcon.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\OldVernVersion.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\OneStoryLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\Options.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\ParatextLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\PlanIcons.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\PlusMinus.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\ProjButtons.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getPlanName'. Either include it or remove the dependency array.","line":87,"column":51,"nodeType":"ArrayExpression","endLine":87,"endColumn":57,"suggestions":[{"desc":"Update the dependencies array to be: [getPlanName, plan]","fix":{"range":[2811,2817],"text":"[getPlanName, plan]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\RecordButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\RecordOrUpload.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\RefRender.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":4,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":4,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\RefRender.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\RemoveNoiseIcon.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\RenderLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\SelectExportType.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\SelectRole.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\ShowLink.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\SpeedMenu.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\Stage.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\StageReport.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\StyledBox.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\StyledHeading.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\StyledMenu.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\TabActions.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\TabBox.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\Tags.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\TemplateEditor.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\TemplateEditorHelpers.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\TemplateEditorUtils.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\ToolbarGrid.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\TranscribeIcon.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\TranscriptionLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\UploadProgress.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/refs').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,37],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable react-hooks/refs */\nimport { useEffect, useRef } from 'react';\nimport { Button } from './Button';\nimport { IUploadProgressStrings } from '../model';\nimport { uploadProgressSelector } from '../selector';\nimport { useSelector } from 'react-redux';\nimport {\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n LinearProgress,\n List,\n ListItem,\n ListItemAvatar,\n ListItemText,\n Avatar,\n Typography,\n Box,\n} from '@mui/material';\nimport CheckIcon from '@mui/icons-material/Check';\n\ninterface IProps {\n open: boolean;\n title?: string;\n progress: number;\n steps?: string[];\n currentStep?: number;\n action?: (choice: string) => void;\n allowCancel?: boolean;\n}\n\nexport function UploadProgress(props: IProps) {\n const { open, title, progress, action, allowCancel } = props;\n const t: IUploadProgressStrings = useSelector(uploadProgressSelector);\n const { steps, currentStep } = props;\n const cancelRef = useRef(false);\n\n const handleChoice = (choice: string) => () => {\n if (!cancelRef.current) {\n cancelRef.current = true;\n if (action) action(choice);\n }\n };\n useEffect(() => {\n if (open) cancelRef.current = false;\n }, [open]);\n\n return (\n \n {title || t.progressTitle}\n \n {steps && currentStep !== undefined && (\n \n {steps.map((s, i) => (\n \n \n \n {currentStep > i && }\n \n \n \n \n ))}\n \n \n )}\n \n \n {cancelRef.current && {t.canceling}}\n \n \n {allowCancel && (\n \n \n {t.cancel}\n \n \n )}\n \n );\n}\n\nexport default UploadProgress;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\UserList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\UserListItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\VertScrollBox.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\VoiceConversionLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\WebFontStyles.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\WrapTitle.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\akuoLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\avatarSize.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\commentProps.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\filteredOptions.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\formatTime.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\iconMargin.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\iconSize.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\initLang.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\layoutSx.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\logosIcon.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\passageTypeFromRef.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\sectionDescription.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\smallBtnProps.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\twIcon.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\control\\userListMode.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\AudioMediaRecorder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\BootstrapFingerprint.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setFingerprint'. Either include it or remove the dependency array.","line":27,"column":6,"nodeType":"ArrayExpression","endLine":27,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [setFingerprint]","fix":{"range":[819,821],"text":"[setFingerprint]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\PassageReference.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\RestoreBackupOnMount.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setProjectsLoaded'. Either include it or remove the dependency array.","line":21,"column":6,"nodeType":"ArrayExpression","endLine":21,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [coordinator, setProjectsLoaded]","fix":{"range":[758,771],"text":"[coordinator, setProjectsLoaded]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\SyncElectronAuthStrings.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\WavRecorder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\__tests__\\AudioMediaRecorder.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\__tests__\\recordPeaksCapture.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\__tests__\\takeRecordingDeltaChunks.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\artifactTypeSlug.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\artifactTypeSlug.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\audacityProjectCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\audioClipboard.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\audioClipboard.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\audioDiagnostics.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\canonicalPersonalWorkflow.adr.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\canonicalPersonalWorkflow.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\captureConstraints.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\captureConstraints.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\computeCommentVisible.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\computeCommentVisible.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\convertToWebM.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\extractSilenceRegions.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\extractSilenceRegions.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\fileOrder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\finalizeRecordingOnDeviceLoss.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\finalizeRecordingOnDeviceLoss.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\fontChoice.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\fontChoice.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\getLwcTranslationAsrSettings.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\getLwcTranslationAsrSettings.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":498,"column":6,"nodeType":"ArrayExpression","endLine":498,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [memory, project]","fix":{"range":[12924,12933],"text":"[memory, project]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\getMediaInPlans.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\getNextStep.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\getOrgs.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\getStepComplete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\groupmembership.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\hasAnyRelated.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\isLinkedNote.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\isLinkedNote.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\isPersonalTeam.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\loadData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\logLoginAnalytics.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\media.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\mediaPassageIdForTranscribe.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\mediaPassageIdForTranscribe.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\nextPasId.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\nextTranscriptionState.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\nextTranscriptionState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\offlineError.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\offlineProjectCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\offlineProjectUpdate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\orbitReset.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\orgWorkflowStepsUtils.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\orgWorkflowStepsUtils.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\passage.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\passagesForSection.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\passagesForSection.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\pickPersonalOrganizationId.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\pickPersonalOrganizationId.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\prevPasId.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\prevPasId.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\pullPlanMedia.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\pullTableList.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\recordPeaksCapture.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\related.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\remoteId.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\resolveBibleForSave.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\resolveBibleForSave.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\restoreBackup.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\saveMediaTranscription.test.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":7,"column":5,"severity":1,"nodeType":null,"fix":{"range":[234,295],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { RecordTransformBuilder } from '@orbit/records';\nimport { MediaFileD } from '../model';\nimport { saveMediaTranscription } from './saveMediaTranscription';\n\njest.mock('../model/baseModel', () => ({\n UpdateRecord: jest.fn(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n (_t: RecordTransformBuilder, rec: MediaFileD, _user: string) => [\n {\n op: 'updateRecord',\n record: rec,\n },\n ]\n ),\n}));\n\ndescribe('saveMediaTranscription', () => {\n it('updates transcription on the mediafile', async () => {\n const update = jest.fn().mockResolvedValue(undefined);\n const memory = { update } as unknown as import('@orbit/memory').default;\n const mediafile = {\n id: 'mf1',\n type: 'mediafile',\n attributes: {\n transcription: 'old',\n dateCreated: '',\n dateUpdated: '',\n lastModifiedBy: 0,\n },\n } as MediaFileD;\n\n await saveMediaTranscription(memory, mediafile, 'new text', 'user1');\n\n expect(update).toHaveBeenCalledTimes(1);\n const ops = update.mock.calls[0][0];\n expect(ops[0].record.attributes.transcription).toBe('new text');\n });\n});\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\saveMediaTranscription.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\saveNewSection.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\section.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\sectionNameOrNumber.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\setDefaultProj.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\stepSpellCheck.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\stepSpellCheck.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\syncToMemory.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\syncToMemory.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\toolSlug.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\transcribeStepAsrSettings.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\tryFindRecord.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\updateBackTranslationType.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\updateConsultantWorkflowStep.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\updatePassageState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useAddToOrgAndGroup.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useAllSharedResourceRead.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useAllUserGroup.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useAllUsers.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useArtifactCategory.language.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useArtifactCategory.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useArtifactCategory.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useArtifactType.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'getTypeId'. Either include it or remove the dependency array.","line":129,"column":6,"nodeType":"ArrayExpression","endLine":129,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [getTypeId]","fix":{"range":[4232,4245],"text":"[getTypeId]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'getTypeId'. Either include it or remove the dependency array.","line":134,"column":6,"nodeType":"ArrayExpression","endLine":134,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [getTypeId]","fix":{"range":[4408,4421],"text":"[getTypeId]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useAudProjName.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useAudacityProjCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useAudacityProjDelete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useAudacityProjRead.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useAudacityProjUpdate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useAvatarSource.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":37,"column":37,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":37,"endColumn":75,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":38,"column":33,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":38,"endColumn":61,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useAvatarSource.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'memory?.keyMap'. Either include it or remove the dependency array.","line":35,"column":6,"nodeType":"ArrayExpression","endLine":35,"endColumn":17,"suggestions":[{"desc":"Update the dependencies array to be: [memory?.keyMap, name, rec]","fix":{"range":[1371,1382],"text":"[memory?.keyMap, name, rec]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useBible.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useBibleBrain.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useBibleMedia.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":25,"column":6,"nodeType":"ArrayExpression","endLine":25,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [memory]","fix":{"range":[943,945],"text":"[memory]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":41,"column":6,"nodeType":"ArrayExpression","endLine":41,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [memory]","fix":{"range":[1474,1476],"text":"[memory]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'getBibleMediaProject' and 'memory'. Either include them or remove the dependency array.","line":55,"column":6,"nodeType":"ArrayExpression","endLine":55,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [getBibleMediaProject, memory]","fix":{"range":[1962,1964],"text":"[getBibleMediaProject, memory]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useCanBeFlat.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useCommitTeamSettings.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useDiscussionCount.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useDiscussionOrg.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useFetchMediaBlob.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchMediaUrl' and 'mediaState'. Either include them or remove the dependency array.","line":91,"column":6,"nodeType":"ArrayExpression","endLine":91,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [fetchMediaUrl, mediaId, mediaState]","fix":{"range":[2321,2330],"text":"[fetchMediaUrl, mediaId, mediaState]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchMediaUrl', 'mediaId', 'mediaState', and 'state.blobStat'. Either include them or remove the dependency array.","line":123,"column":6,"nodeType":"ArrayExpression","endLine":123,"endColumn":22,"suggestions":[{"desc":"Update the dependencies array to be: [fetchMediaUrl, mediaId, mediaState, mediaState.url, state.blobStat]","fix":{"range":[3490,3506],"text":"[fetchMediaUrl, mediaId, mediaState, mediaState.url, state.blobStat]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useFetchMediaUrl.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchUrl', 'getGlobal', 'memory.cache', 'reporter', 'state.remoteId', and 'ts.expiredToken'. Either include them or remove the dependency array.","line":208,"column":6,"nodeType":"ArrayExpression","endLine":208,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [fetchUrl, getGlobal, memory.cache, reporter, state.id, state.remoteId, ts.expiredToken]","fix":{"range":[6113,6123],"text":"[fetchUrl, getGlobal, memory.cache, reporter, state.id, state.remoteId, ts.expiredToken]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useFetchUrlNow.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useFilteredSteps.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'filtered'. Either include it or remove the dependency array.","line":59,"column":34,"nodeType":"ArrayExpression","endLine":59,"endColumn":44,"suggestions":[{"desc":"Update the dependencies array to be: [filtered]","fix":{"range":[1988,1998],"text":"[filtered]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useFlatAdd.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useGetAsrSettings.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useGetAsrSettings.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useMemo has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":103,"column":6,"nodeType":"ArrayExpression","endLine":103,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [memory, project]","fix":{"range":[3619,3628],"text":"[memory, project]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useGraphicCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useGraphicFind.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useGraphicUpdate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useGraphicUrlBuilder.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":186,"column":9,"severity":1,"nodeType":null,"fix":{"range":[6230,6291],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has an unnecessary dependency: 'lang'. Either exclude it or remove the dependency array.","line":97,"column":6,"nodeType":"ArrayExpression","endLine":97,"endColumn":25,"suggestions":[{"desc":"Update the dependencies array to be: [allBookData]","fix":{"range":[3045,3064],"text":"[allBookData]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'refFromQuery', 'setQBook', and 'setQRef'. Either include them or remove the dependency array.","line":228,"column":5,"nodeType":"ArrayExpression","endLine":228,"endColumn":35,"suggestions":[{"desc":"Update the dependencies array to be: [refFromQuery, setQBook, setQRef, buildGraphicUrl]","fix":{"range":[7641,7671],"text":"[refFromQuery, setQBook, setQRef, buildGraphicUrl]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { useCallback, useMemo } from 'react';\nimport { parseRef } from './passage';\nimport { pad3 } from '../utils/pad3';\nimport { IState, PassageD } from '../model';\nimport CodeNum from '../assets/code-num.json';\nimport { type ScriptureRefChecked } from '../components/GraphicImageFilter';\nimport { useSelector } from 'react-redux';\nimport { chapterMatch, refMatch } from '../utils/refMatch';\nimport { API_CONFIG } from '../../api-variable';\n\nconst codeNumMap = new Map(\n (CodeNum as [string, number][]).map(([code, num]) => [code, num])\n);\n\nexport interface GraphicFilterState {\n /** Style (s) parameter */\n s?: string;\n /** Keyword (k) parameter */\n k?: string;\n}\n\nexport interface GetUrlOptions {\n /** Page number (default 1) */\n page?: number;\n /** Page size (default 100) */\n limit?: number;\n}\n\nexport interface GetKeywordUrlOptions extends GetUrlOptions {\n /** styles (s) parameter */\n s?: string;\n}\n\nexport interface GetStyleUrlOptions extends GetUrlOptions {\n /** keywords (k) parameter */\n k?: string;\n}\n\nexport interface GetSearchUrlOptions extends GetUrlOptions {\n /** Search query (q) */\n query: string;\n /** Style and keyword filters */\n filterState?: GraphicFilterState;\n /** Sort by newest (default true) */\n sortByNewest?: boolean;\n}\n\nexport interface ScriptureRange {\n book_code: string;\n start_idx: number;\n end_idx: number;\n}\n\n/**\n * Builds start_idx / end_idx in BBCCCVVV format from book code and chapter/verse.\n * BB = pad2(book number from code-num), CCC = pad3(chapter), VVV = pad3(verse).\n */\nfunction toScriptureIndex(\n bookCode: string,\n chapter: number,\n verse: number\n): number {\n const bookNum = codeNumMap.get(bookCode) ?? 0;\n const bb = bookNum.toString();\n const ccc = pad3(chapter);\n const vvv = pad3(verse);\n return parseInt(bb + ccc + vvv, 10);\n}\n\n/**\n * Hook that builds the graphic search API URL for a section.\n * Uses sectionId to resolve section + passages, then sectionRef logic to get\n * book_code and start_idx/end_idx. Dispatches fetchBooks so book short name (b) is available.\n * Pass query, filterState, page, limit, sortByNewest to getSearchUrl() to build the URL.\n */\nexport function useGraphicUrlBuilder(\n bookCode: string,\n reference: string,\n scriptureRefChecked: ScriptureRefChecked,\n refOverride: boolean,\n setQBook: (book: string | undefined) => void,\n setQRef: (ref: string | undefined) => void\n) {\n // if users sets a book or reference in the query...\n const lang = useSelector((state: IState) => state.strings.lang);\n const allBookData = useSelector((state: IState) => state.books.bookData);\n const bookNameMap = useMemo(() => {\n const dataMap = new Map();\n allBookData.forEach((book) => {\n dataMap.set(book.short.toLocaleUpperCase(), book.code);\n dataMap.set(book.long.toLocaleUpperCase(), book.code);\n dataMap.set(book.abbr.toLocaleUpperCase(), book.code);\n dataMap.set(book.code, book.code);\n });\n return dataMap;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [allBookData, lang]);\n\n const psgRefParts = useMemo(() => {\n const psg = {\n attributes: { book: bookCode, reference: reference },\n } as PassageD;\n parseRef(psg);\n return {\n startChapter: psg.attributes.startChapter,\n startVerse: psg.attributes.startVerse,\n endChapter: psg.attributes.endChapter,\n endVerse: psg.attributes.endVerse,\n };\n }, [bookCode, reference]);\n\n const scriptureRange = useMemo((): ScriptureRange | undefined => {\n const startChapter =\n scriptureRefChecked.chapter || refOverride\n ? (psgRefParts?.startChapter ?? 1)\n : 1;\n const startVerse =\n scriptureRefChecked.verse || refOverride\n ? (psgRefParts?.startVerse ?? 1)\n : 1;\n const endChapter =\n scriptureRefChecked.chapter || refOverride\n ? (psgRefParts?.endChapter ?? startChapter)\n : 999;\n const endVerse =\n scriptureRefChecked.verse || refOverride\n ? (psgRefParts?.endVerse ?? startVerse)\n : 999;\n const start_idx = toScriptureIndex(bookCode, startChapter, startVerse);\n const end_idx = toScriptureIndex(bookCode, endChapter, endVerse);\n return { book_code: bookCode, start_idx, end_idx };\n }, [psgRefParts, scriptureRefChecked, bookCode, refOverride]);\n\n const buildGraphicUrl = useCallback(\n (\n endpoint: string,\n baseOptions: { page?: number; limit?: number },\n addParams: (append: (key: string, value: string) => void) => void\n ): string | undefined => {\n if (!scriptureRange || !API_CONFIG.graphicApiBase) return undefined;\n const pairs: [string, string][] = [];\n const append = (key: string, value: string) => pairs.push([key, value]);\n\n append('page', String(baseOptions.page ?? 1));\n append('limit', String(baseOptions.limit ?? 100));\n addParams(append);\n if (scriptureRefChecked.book || refOverride) {\n append(\n 'scripture',\n JSON.stringify({\n book_code: scriptureRange.book_code,\n start_idx: scriptureRange.start_idx,\n end_idx: scriptureRange.end_idx,\n })\n );\n }\n const queryString = pairs\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&');\n return `${API_CONFIG.graphicApiBase}/${endpoint}?${queryString}`;\n },\n [scriptureRange, scriptureRefChecked, refOverride]\n );\n\n const refFromQuery = (\n query: string,\n setQBook?: (book: string | undefined) => void,\n setQRef?: (ref: string | undefined) => void\n ) => {\n let pquery = query.trim();\n const mBook = /^([1-5])\\s([^\\s]+)/.exec(pquery);\n if (mBook) {\n pquery = `${mBook[1]}_${mBook[2]}${pquery.slice(mBook[0].length)}`;\n }\n // check for book and reference in the query\n const words = pquery.split(' ');\n const book = words[0].replace('_', ' ');\n if (book && bookNameMap.has(book.toLocaleUpperCase())) {\n const newCode = bookNameMap.get(book.toLocaleUpperCase()) as string;\n if (newCode && (!refOverride || newCode !== bookCode)) {\n setQBook?.(newCode);\n }\n const ref = words[1];\n const m = chapterMatch(ref);\n if (ref && m) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [_, start, end] = m;\n let chapterRef = `${start}:1-`;\n if (end) chapterRef += `${end}:`;\n chapterRef += '999';\n setQRef?.(chapterRef);\n query = query.replace(`${mBook?.[0] ?? words[0]} ${ref}`, '');\n } else if (ref && refMatch(ref)) {\n setQRef?.(ref);\n query = query.replace(`${mBook?.[0] ?? words[0]} ${ref}`, '');\n } else {\n setQRef?.('1:1-999:999');\n query = query.replace(mBook?.[0] ?? words[0], '');\n }\n } else {\n setQBook?.(undefined);\n setQRef?.(undefined);\n }\n return query.trim();\n };\n\n const getSearchUrl = useCallback(\n (options: GetSearchUrlOptions): string | undefined => {\n const {\n filterState = {},\n page = 1,\n limit = 100,\n sortByNewest = true,\n } = options;\n const query = refFromQuery(options.query, setQBook, setQRef);\n return buildGraphicUrl('search', { page, limit }, (append) => {\n append('q', query);\n append('sortByNewest', String(sortByNewest));\n if (filterState.k != null && filterState.k !== '') {\n append('k', filterState.k);\n }\n if (filterState.s != null && filterState.s !== '') {\n append('s', filterState.s);\n }\n });\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [buildGraphicUrl, bookNameMap]\n );\n\n const getKeywordUrl = useCallback(\n (options: GetKeywordUrlOptions): string | undefined => {\n const { s, page = 1, limit = 100 } = options;\n return buildGraphicUrl('keywords', { page, limit }, (append) => {\n if (s != null && s !== '') {\n append('s', s);\n }\n });\n },\n [buildGraphicUrl]\n );\n\n const getStyleUrl = useCallback(\n (options: GetStyleUrlOptions): string | undefined => {\n const { k, page = 1, limit = 100 } = options;\n return buildGraphicUrl('styles', { page, limit }, (append) => {\n if (k != null && k !== '') {\n append('k', k);\n }\n });\n },\n [buildGraphicUrl]\n );\n\n return {\n /** Scripture range for the API */\n scriptureRange,\n /** Build the search URL from query, filterState, page, limit, sortByNewest */\n getSearchUrl,\n /** Build the keyword URL from styles, page, limit */\n getKeywordUrl,\n /** Build the style URL from keywords, page, limit */\n getStyleUrl,\n /** Get Reference from Query */\n refFromQuery,\n };\n}\n\nexport default useGraphicUrlBuilder;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useGroupOrUser.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useKeyTermSave.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useLoadProjectData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useLoadStatic.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useMediaAttach.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useMediaCounts.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useMediaResCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useMediaUpload.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":143,"column":37,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":143,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":168,"column":28,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":168,"endColumn":61,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":169,"column":32,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":169,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":183,"column":28,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":183,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":425,"column":32,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":425,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":441,"column":33,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":441,"endColumn":66,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":442,"column":32,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":442,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useMediaUpload.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useNewTeamId.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useNoteCategory.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useNoteCategory.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useNotes.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useOfflineAvailToggle.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useOfflineList.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useOfflineSetup.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useOfflnMediafileCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useOfflnProjCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useOfflnProjDelete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useOfflnProjRead.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useOrgDefaults.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useOrgMembers.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getMbrRole'. Either include it or remove the dependency array.","line":57,"column":6,"nodeType":"ArrayExpression","endLine":57,"endColumn":67,"suggestions":[{"desc":"Update the dependencies array to be: [organization, team, users, orgmems, offlineOnly, listAdmins, getMbrRole]","fix":{"range":[1723,1784],"text":"[organization, team, users, orgmems, offlineOnly, listAdmins, getMbrRole]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useOrgWorkflowSteps.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useOrganizedBy.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\usePassageRec.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\usePassageState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\usePassageType.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\usePassageUpdate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\usePermissions.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'permissions'. Either include it or remove the dependency array.","line":42,"column":6,"nodeType":"ArrayExpression","endLine":42,"endColumn":16,"suggestions":[{"desc":"Update the dependencies array to be: [myGroups, permissions]","fix":{"range":[1431,1441],"text":"[myGroups, permissions]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\usePlan.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\usePlanType.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useProjectDefaults.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useProjectDelete.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useProjectDelete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useProjectExport.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useProjectPlans.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useProjectType.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\usePublishDestination.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\usePublishLevel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useRecOfType.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useRole.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'getMyOrgRole' and 'setOrgRole'. Either include them or remove the dependency array.","line":116,"column":5,"nodeType":"ArrayExpression","endLine":116,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [getMyOrgRole, orgRole, setOrgRole]","fix":{"range":[3786,3795],"text":"[getMyOrgRole, orgRole, setOrgRole]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSanityCheck.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSaveComment.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSecResCreate.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'InternalizationStep'. Either include it or remove the dependency array.","line":34,"column":6,"nodeType":"ArrayExpression","endLine":34,"endColumn":33,"suggestions":[{"desc":"Update the dependencies array to be: [InternalizationStep]","fix":{"range":[1238,1265],"text":"[InternalizationStep]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSecResDelete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSecResUpdate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSecResUserCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSecResUserDelete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSecResUserRead.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSectionCounts.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useShaRefCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useShaRefDelete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useShaRefRead.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useShaRefUpdate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSharedResCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSharedResDelete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSharedResRead.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSharedResRead.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'memory?.cache'. Either include it or remove the dependency array.","line":37,"column":6,"nodeType":"ArrayExpression","endLine":37,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [memory?.cache]","fix":{"range":[1376,1378],"text":"[memory?.cache]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":51,"column":5,"nodeType":"ArrayExpression","endLine":51,"endColumn":25,"suggestions":[{"desc":"Update the dependencies array to be: [memory, readSharedResource]","fix":{"range":[1754,1774],"text":"[memory, readSharedResource]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useSharedResUpdate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useShowAssignment.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useShowAssignment.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useStepTool.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useStepTool.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":60,"column":6,"nodeType":"ArrayExpression","endLine":60,"endColumn":29,"suggestions":[{"desc":"Update the dependencies array to be: [stepId, memory]","fix":{"range":[1787,1810],"text":"[stepId, memory]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useTableType.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useTeamApiPull.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useTeamCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useTeamDelete.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useTeamDelete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useTeamRead.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useTeamUpdate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useTeamWorkflowProcess.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useTools.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/immutability').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,45],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable react-hooks/immutability */\nimport { useState } from 'react';\nimport { IState, OptionType, IToolStrings } from '../model';\nimport localStrings from '../selector/localize';\nimport { useSelector, shallowEqual } from 'react-redux';\nimport { ToolSlug } from '.';\nimport { addPt } from '../utils/addPt';\n\nconst toolSlugs = [\n ToolSlug.Resource,\n ToolSlug.Prompt,\n ToolSlug.Record,\n ToolSlug.KeyTerm,\n ToolSlug.TeamCheck,\n ToolSlug.Community,\n ToolSlug.Discuss,\n ToolSlug.Verses,\n ToolSlug.Transcribe,\n ToolSlug.PhraseBackTranslate,\n ToolSlug.CarefulSpeech,\n ToolSlug.WholeBackTranslate,\n ToolSlug.Paratext,\n ToolSlug.ConsultantCheck,\n ToolSlug.Export,\n ToolSlug.Done,\n];\n\ninterface ISwitches {\n [key: string]: any;\n}\nconst stringSelector = (state: IState) =>\n localStrings(state as IState, { layout: 'tool' });\n\nexport const useTools = () => {\n const t: IToolStrings = useSelector(stringSelector, shallowEqual);\n const [fromLocal] = useState({});\n\n const localizedTool = (val: string) => {\n return addPt((t as ISwitches)[val] ?? '') || val;\n };\n\n const fromLocalizedTool = (val: string) => {\n if (Object.entries(fromLocal).length === 0) {\n for (const [key, value] of Object.entries(t)) {\n fromLocal[addPt(value)] = addPt(key);\n }\n }\n return fromLocal[addPt(val)] || val;\n };\n\n const getToolOptions = () => {\n return toolSlugs.map(\n (v) =>\n ({\n label: localizedTool(v),\n value: v,\n }) as OptionType\n );\n };\n\n return {\n getToolOptions,\n localizedTool,\n fromLocalizedTool,\n };\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useTranscription.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useTypeId.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useUiLang.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useUpdateOrbitToken.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/immutability').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,45],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable react-hooks/immutability */\nimport { useGlobal } from '../context/useGlobal';\nimport JSONAPISource from '@orbit/jsonapi';\nimport { syncRemoteAuthHeaders } from '../utils/syncRemoteAuthHeaders';\n\nexport const useUpdateOrbitToken = () => {\n const [coordinator] = useGlobal('coordinator');\n const [fingerprint] = useGlobal('fingerprint');\n\n return (myToken: string) => {\n const remote = coordinator?.getSource('remote') as JSONAPISource;\n const datachangeremote = coordinator?.getSource(\n 'datachanges'\n ) as JSONAPISource;\n syncRemoteAuthHeaders(remote, myToken, fingerprint || '');\n syncRemoteAuthHeaders(datachangeremote, myToken, fingerprint || '');\n };\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useUpdateRecord.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useUrlContext.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useUser.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useUserMedia.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useUserMedia.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useVProjectCreate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useVProjectDelete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useVProjectRead.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useVProjectUpdate.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useVoiceUrl.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useWavRecorder.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useWavRecorder.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps').","line":189,"column":5,"severity":1,"nodeType":null,"fix":{"range":[6220,6275],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getMediaStream', 'handleError', 'showMessage', and 'takeCaptureStream'. Either include them or remove the dependency array.","line":252,"column":6,"nodeType":"ArrayExpression","endLine":252,"endColumn":75,"suggestions":[{"desc":"Update the dependencies array to be: [allowRecord, deviceId, echoCancellation, getMediaStream, handleError, noiseSuppression, reporter, showMessage, takeCaptureStream]","fix":{"range":[8341,8410],"text":"[allowRecord, deviceId, echoCancellation, getMediaStream, handleError, noiseSuppression, reporter, showMessage, takeCaptureStream]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { useGlobal } from '../context/useGlobal';\nimport { useEffect, useMemo, useRef } from 'react';\nimport { CaptureAcquireSupersededError, useUserMedia } from './useUserMedia';\nimport { useSnackBar } from '../hoc/SnackBar';\nimport { logError, Severity } from '../utils';\nimport { createWavRecorder } from './WavRecorder';\nimport { createAudioMediaRecorder } from './AudioMediaRecorder';\nimport {\n createRecordPeaksCapture,\n RecordPeaksCapture,\n} from './recordPeaksCapture';\nimport {\n getAudioTrackDiagnostics,\n getBlobDiagnostics,\n logAudioDiagnostic,\n} from './audioDiagnostics';\nimport {\n buildCaptureConstraints,\n CaptureDeviceLostError,\n captureStreamDeviceId,\n isDeviceLossError,\n isUnusableCaptureStream,\n listenForCaptureDeviceLoss,\n waitOutTransientCaptureMute,\n} from './captureConstraints';\n\n/** Defaults match Record step toolSettings when keys are absent (both off). */\nexport function parseRecordCaptureAudioProcessing(\n toolSettings: string | undefined | null\n): { echoCancellation: boolean; noiseSuppression: boolean } {\n if (!toolSettings?.trim()) {\n return { echoCancellation: false, noiseSuppression: false };\n }\n try {\n const j = JSON.parse(toolSettings) as {\n echoCancellation?: boolean;\n noiseSuppression?: boolean;\n };\n return {\n echoCancellation: Boolean(j.echoCancellation),\n noiseSuppression: Boolean(j.noiseSuppression),\n };\n } catch {\n return { echoCancellation: false, noiseSuppression: false };\n }\n}\n\nconst noop = () => {};\n\nexport interface MimeInfo {\n mimeType: string;\n extension: string;\n}\n\n// Type for recorder that can be either WavRecorder or AudioMediaRecorder\nexport interface APMRecorder {\n initializeWorklet(): Promise;\n start(timeSlice?: number): Promise;\n stop(): Promise;\n cleanup(): void;\n}\n\n// Check if AudioWorklet is available (not available on iOS Safari)\nfunction isAudioWorkletAvailable(): boolean {\n try {\n // Check if AudioWorklet is supported\n if (typeof AudioWorklet === 'undefined') {\n return false;\n }\n // Try to create an AudioContext to verify\n const context = new AudioContext();\n const isSupported = typeof context.audioWorklet !== 'undefined';\n // Close the context to avoid leaking audio resources\n void context.close();\n return isSupported;\n } catch {\n return false;\n }\n}\n\nexport function useWavRecorder(\n allowRecord: boolean = true,\n onStart: () => void = noop,\n onStop: (blob?: Blob) => void = noop,\n onError: (e: any) => void = noop,\n onDataAvailable: (blob: Blob) => Promise,\n deviceId?: string,\n echoCancellation: boolean = false,\n noiseSuppression: boolean = false,\n /** Live waveform peaks (cheap render path) — see recordPeaksCapture.ts. */\n onLivePeaks?: (peaks: Float32Array, seconds: number) => void\n) {\n const recorderRef = useRef(undefined);\n const useFallbackRef = useRef(null); // null = not checked yet\n const isRecordingRef = useRef(false);\n const peaksCaptureRef = useRef(undefined);\n const recordingStartedAtRef = useRef(undefined);\n const captureOptions = useMemo(\n () => buildCaptureConstraints(deviceId, echoCancellation, noiseSuppression),\n [deviceId, echoCancellation, noiseSuppression]\n );\n const getMediaStream = useUserMedia(captureOptions);\n const mediaStreamRef = useRef(undefined);\n const ignoreTrackEndedRef = useRef(false);\n const stopWatchingStreamRef = useRef<() => void>(() => undefined);\n const previousDeviceIdRef = useRef(undefined);\n const recorderStreamIdRef = useRef(undefined);\n const captureGenerationRef = useRef(0);\n const recorderStopRef = useRef<\n | {\n recorder: APMRecorder;\n stop: Promise;\n published?: Promise;\n settled?: boolean;\n }\n | undefined\n >(undefined);\n const takeFinalizationRef = useRef | undefined>(undefined);\n const dropStreamQueuedRef = useRef(false);\n const suppressPreviewRef = useRef(false);\n const startingRef = useRef(false);\n const [reporter] = useGlobal('errorReporter');\n const { showMessage } = useSnackBar();\n\n function dropCaptureStream() {\n ignoreTrackEndedRef.current = true;\n stopWatchingStreamRef.current();\n stopWatchingStreamRef.current = () => undefined;\n mediaStreamRef.current?.getTracks().forEach((track) => {\n try {\n track.stop();\n } catch {\n /* device already gone */\n }\n });\n mediaStreamRef.current = undefined;\n }\n\n function adoptCaptureStream(stream: MediaStream) {\n stopWatchingStreamRef.current();\n ignoreTrackEndedRef.current = false;\n mediaStreamRef.current = stream;\n stopWatchingStreamRef.current = listenForCaptureDeviceLoss(\n stream,\n () => {\n if (!ignoreTrackEndedRef.current) {\n handleError(new CaptureDeviceLostError());\n }\n },\n () => isRecordingRef.current || takeFinalizationRef.current !== undefined\n );\n }\n\n function takeCaptureStream(stream: MediaStream, fellBack: boolean) {\n adoptCaptureStream(stream);\n logAudioDiagnostic('media-stream-ready', {\n requestedCaptureOptions: captureOptions,\n selectedDeviceId: deviceId,\n stream: { id: stream.id, active: stream.active },\n tracks: getAudioTrackDiagnostics(stream),\n });\n if (fellBack) {\n onError({\n error: 'microphone disconnected',\n deviceLost: true,\n fellBack: true,\n deviceId: captureStreamDeviceId(stream),\n });\n }\n }\n\n useEffect(() => {\n return () => {\n captureGenerationRef.current += 1;\n suppressPreviewRef.current = true;\n peaksCaptureRef.current?.stop();\n peaksCaptureRef.current = undefined;\n const recorder = recorderRef.current;\n dropCaptureStream();\n if (startingRef.current) return;\n if (recorder && (isRecordingRef.current || takeFinalizationRef.current)) {\n void ensureRecorderStopped(recorder)\n .catch(() => undefined)\n .then(() => discardRecorder(recorder));\n } else {\n discardRecorder(recorder);\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const captureProcessingKeyRef = useRef('');\n\n useEffect(() => {\n const generation = ++captureGenerationRef.current;\n if (!allowRecord) {\n dropCaptureStream();\n previousDeviceIdRef.current = deviceId;\n captureProcessingKeyRef.current = '';\n return;\n }\n\n const processingKey = `${echoCancellation},${noiseSuppression}`;\n const processingChanged =\n captureProcessingKeyRef.current !== '' &&\n captureProcessingKeyRef.current !== processingKey &&\n mediaStreamRef.current !== undefined;\n\n if (processingChanged && !isRecordingRef.current) {\n dropCaptureStream();\n }\n\n const deviceChanged =\n previousDeviceIdRef.current !== deviceId &&\n mediaStreamRef.current !== undefined;\n const streamGone = isUnusableCaptureStream(mediaStreamRef.current);\n\n const ensureStream = async () => {\n try {\n const { stream, fellBack } = await getMediaStream(\n deviceChanged || processingChanged || streamGone\n );\n if (generation !== captureGenerationRef.current) return;\n if (stream && stream.id && stream.active) {\n takeCaptureStream(stream, fellBack);\n } else {\n const err = 'no media stream ' + stream?.toString();\n logError(Severity.error, reporter, err);\n showMessage(err);\n }\n } catch (e) {\n if (generation !== captureGenerationRef.current) return;\n if (e instanceof CaptureAcquireSupersededError) return;\n handleError(e as Error);\n }\n };\n\n if (isRecordingRef.current) {\n if (streamGone) handleError(new CaptureDeviceLostError());\n } else if (streamGone || deviceChanged || processingChanged) {\n ensureStream();\n }\n\n if ((deviceChanged || processingChanged) && !isRecordingRef.current) {\n recorderRef.current = undefined;\n recorderStreamIdRef.current = undefined;\n }\n\n previousDeviceIdRef.current = deviceId;\n captureProcessingKeyRef.current = processingKey;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [allowRecord, deviceId, echoCancellation, noiseSuppression, reporter]);\n\n function handleError(e: any) {\n const message =\n e?.error || e?.message || e?.toString?.() || 'Recorder error';\n logError(Severity.error, reporter, message);\n if (isDeviceLossError(e)) {\n ignoreTrackEndedRef.current = true;\n stopWatchingStreamRef.current();\n stopWatchingStreamRef.current = () => undefined;\n void finalizeTake({ dropStream: true });\n onError({ error: message, deviceLost: true });\n return;\n }\n onError({ error: message });\n }\n\n function discardRecorder(recorder: APMRecorder | undefined) {\n if (!recorder) return;\n try {\n recorder.cleanup();\n } catch {\n /* AudioContext may already be shut down */\n }\n }\n\n function ensureRecorderStopped(\n recorder: APMRecorder\n ): Promise {\n const slot = recorderStopRef.current;\n if (slot?.recorder === recorder && !slot.settled) {\n return slot.stop;\n }\n const stop = recorder\n .stop()\n .then((blob) => (blob.size > 0 ? blob : undefined))\n .catch(() => undefined);\n recorderStopRef.current = { recorder, stop, settled: false };\n void stop.finally(() => {\n if (recorderStopRef.current?.stop === stop) {\n recorderStopRef.current.settled = true;\n }\n });\n return stop;\n }\n\n function publishTake(blob: Blob | undefined): Promise {\n const slot = recorderStopRef.current;\n if (slot?.published) return slot.published;\n const published = Promise.resolve(onStop(blob)).then(() => undefined);\n if (slot) slot.published = published;\n return published;\n }\n\n function finalizeTake(opts: { dropStream: boolean }): Promise {\n if (!takeFinalizationRef.current) {\n const recorder = recorderRef.current;\n const wasRecording = isRecordingRef.current;\n suppressPreviewRef.current = true;\n isRecordingRef.current = false;\n peaksCaptureRef.current?.stop();\n peaksCaptureRef.current = undefined;\n takeFinalizationRef.current = (async () => {\n if (recorder && wasRecording) {\n const blob = await ensureRecorderStopped(recorder);\n const durationSeconds = recordingStartedAtRef.current\n ? (performance.now() - recordingStartedAtRef.current) / 1000\n : undefined;\n logAudioDiagnostic('recording-stopped', {\n fallbackRecorder: useFallbackRef.current,\n recordedBlob: blob\n ? getBlobDiagnostics(blob, durationSeconds)\n : undefined,\n tracks: mediaStreamRef.current\n ? getAudioTrackDiagnostics(mediaStreamRef.current)\n : undefined,\n });\n recordingStartedAtRef.current = undefined;\n await publishTake(blob);\n }\n })();\n }\n if (opts.dropStream && !dropStreamQueuedRef.current) {\n dropStreamQueuedRef.current = true;\n takeFinalizationRef.current = takeFinalizationRef.current.finally(() => {\n const recorder =\n recorderRef.current ?? recorderStopRef.current?.recorder;\n discardRecorder(recorder);\n if (recorderRef.current === recorder) {\n recorderRef.current = undefined;\n recorderStreamIdRef.current = undefined;\n }\n dropCaptureStream();\n });\n }\n const chain = takeFinalizationRef.current;\n return chain.finally(() => {\n if (takeFinalizationRef.current === chain) {\n takeFinalizationRef.current = undefined;\n dropStreamQueuedRef.current = false;\n }\n });\n }\n\n async function discardStartedRecorder(recorder: APMRecorder) {\n suppressPreviewRef.current = true;\n await ensureRecorderStopped(recorder);\n discardRecorder(recorder);\n if (recorderRef.current === recorder) {\n recorderRef.current = undefined;\n recorderStreamIdRef.current = undefined;\n }\n }\n\n function recorderStillCurrent(\n generation: number,\n stream: MediaStream | undefined\n ) {\n return (\n generation === captureGenerationRef.current &&\n stream !== undefined &&\n mediaStreamRef.current === stream\n );\n }\n\n function emitPreview(blob: Blob) {\n if (suppressPreviewRef.current) return;\n void onDataAvailable(blob);\n }\n\n async function startRecorder() {\n const generation = captureGenerationRef.current;\n if (await waitOutTransientCaptureMute(mediaStreamRef.current)) {\n if (generation !== captureGenerationRef.current) return undefined;\n try {\n const { stream, fellBack } = await getMediaStream(true);\n if (generation !== captureGenerationRef.current) return undefined;\n takeCaptureStream(stream, fellBack);\n } catch (error) {\n if (error instanceof CaptureAcquireSupersededError) return undefined;\n handleError(error);\n return undefined;\n }\n }\n const stream = mediaStreamRef.current;\n if (!stream || generation !== captureGenerationRef.current) {\n return undefined;\n }\n try {\n // Check AudioWorklet availability (cache the result)\n if (useFallbackRef.current === null) {\n useFallbackRef.current = !isAudioWorkletAvailable();\n logAudioDiagnostic('recorder-capability-check', {\n audioWorkletAvailable: !useFallbackRef.current,\n fallbackRecorder: useFallbackRef.current,\n });\n }\n let recorder: APMRecorder;\n\n if (useFallbackRef.current) {\n logAudioDiagnostic('recorder-selected', {\n recorderType: 'MediaRecorder',\n fallbackRecorder: true,\n reason: 'AudioWorklet unavailable',\n tracks: getAudioTrackDiagnostics(stream),\n });\n recorder = createAudioMediaRecorder(stream, emitPreview);\n } else {\n // Use WavRecorder with AudioWorklet (when we need WAV format)\n logAudioDiagnostic('recorder-selected', {\n recorderType: 'AudioWorkletWavRecorder',\n fallbackRecorder: false,\n tracks: getAudioTrackDiagnostics(stream),\n });\n recorder = createWavRecorder(stream, emitPreview);\n }\n\n await recorder.initializeWorklet();\n if (!recorderStillCurrent(generation, stream)) {\n discardRecorder(recorder);\n return undefined;\n }\n recorderRef.current = recorder;\n recorderStreamIdRef.current = stream.id;\n return recorder;\n } catch (error) {\n // If WavRecorder fails, try fallback\n if (!useFallbackRef.current) {\n try {\n useFallbackRef.current = true;\n logAudioDiagnostic('recorder-fallback-after-error', {\n fallbackRecorder: true,\n error:\n error instanceof Error\n ? { name: error.name, message: error.message }\n : { message: String(error) },\n tracks: getAudioTrackDiagnostics(stream),\n });\n const fallbackRecorder = createAudioMediaRecorder(\n stream,\n emitPreview\n );\n await fallbackRecorder.initializeWorklet();\n if (!recorderStillCurrent(generation, stream)) {\n discardRecorder(fallbackRecorder);\n return undefined;\n }\n recorderRef.current = fallbackRecorder;\n recorderStreamIdRef.current = stream.id;\n return fallbackRecorder;\n } catch (fallbackError) {\n handleError(fallbackError);\n return undefined;\n }\n } else {\n handleError(error);\n return undefined;\n }\n }\n }\n\n async function startRecording(timeSlice?: number) {\n if (takeFinalizationRef.current) {\n await takeFinalizationRef.current;\n }\n recorderStopRef.current = undefined;\n const generation = captureGenerationRef.current;\n const streamMuted = Boolean(\n mediaStreamRef.current?.getAudioTracks?.()[0]?.muted\n );\n let recorder = recorderRef.current;\n if (\n !recorder ||\n recorderStreamIdRef.current !== mediaStreamRef.current?.id ||\n isUnusableCaptureStream(mediaStreamRef.current) ||\n streamMuted\n ) {\n recorder = await startRecorder();\n }\n if (generation !== captureGenerationRef.current) {\n discardRecorder(recorder);\n if (recorderRef.current === recorder) {\n recorderRef.current = undefined;\n recorderStreamIdRef.current = undefined;\n }\n return false;\n }\n if (recorder) {\n try {\n suppressPreviewRef.current = true;\n startingRef.current = true;\n try {\n await recorder.start(timeSlice);\n } finally {\n startingRef.current = false;\n }\n if (!recorderStillCurrent(generation, mediaStreamRef.current)) {\n await discardStartedRecorder(recorder);\n return false;\n }\n suppressPreviewRef.current = false;\n recordingStartedAtRef.current = performance.now();\n logAudioDiagnostic('recording-started', {\n timeSliceMs: timeSlice,\n fallbackRecorder: useFallbackRef.current,\n requestedCaptureOptions: captureOptions,\n selectedDeviceId: deviceId,\n tracks: mediaStreamRef.current\n ? getAudioTrackDiagnostics(mediaStreamRef.current)\n : undefined,\n });\n isRecordingRef.current = true;\n if (onLivePeaks && mediaStreamRef.current) {\n peaksCaptureRef.current?.stop();\n peaksCaptureRef.current = createRecordPeaksCapture(\n mediaStreamRef.current,\n onLivePeaks\n );\n }\n onStart();\n return true;\n } catch (error) {\n handleError(error);\n return false;\n }\n } else {\n onError({ error: 'No recorder available' });\n return false;\n }\n }\n\n function stopRecording() {\n if (takeFinalizationRef.current) return;\n if (!isRecordingRef.current || !recorderRef.current) {\n onError({ error: 'Not recording' });\n return;\n }\n void finalizeTake({ dropStream: false });\n }\n return {\n startRecording: allowRecord\n ? (timeSlice?: number) => startRecording(timeSlice)\n : () => Promise.resolve(false),\n stopRecording: allowRecord ? stopRecording : noop,\n };\n}\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useWaveSurfer.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setProgress'. Either include it or remove the dependency array.","line":236,"column":6,"nodeType":"ArrayExpression","endLine":236,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [currentTime, setProgress]","fix":{"range":[9172,9185],"text":"[currentTime, setProgress]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'Regions', 'errorReporter', 'isMobile', 'loadRegions', 'onInteraction', 'onPlayStatus', 'onReady', 'onZoom', 'prepareForDestroy', 'setDuration', 'setPlaying', 'setupRegions', 'setupZoom', 'singleRegionOnly', 'wsAddRegion', 'wsGoto', 'wsLoad', and 'wsRemoveCurrentRegion'. Either include them or remove the dependency array. If 'onReady' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":551,"column":6,"nodeType":"ArrayExpression","endLine":551,"endColumn":18,"suggestions":[{"desc":"Update the dependencies array to be: [Regions, errorReporter, isMobile, loadRegions, onInteraction, onPlayStatus, onReady, onZoom, prepareForDestroy, setDuration, setPlaying, setupRegions, setupZoom, singleRegionOnly, wavesurfer, wsAddRegion, wsGoto, wsLoad, wsRemoveCurrentRegion]","fix":{"range":[19522,19534],"text":"[Regions, errorReporter, isMobile, loadRegions, onInteraction, onPlayStatus, onReady, onZoom, prepareForDestroy, setDuration, setPlaying, setupRegions, setupZoom, singleRegionOnly, wavesurfer, wsAddRegion, wsGoto, wsLoad, wsRemoveCurrentRegion]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'prepareForDestroy' and 'throttledProgressCallback'. Either include them or remove the dependency array.","line":588,"column":6,"nodeType":"ArrayExpression","endLine":588,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [prepareForDestroy, throttledProgressCallback]","fix":{"range":[20629,20631],"text":"[prepareForDestroy, throttledProgressCallback]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useWavesurferRegions.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\useWavesurferRegions.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'applyBoundaryEditability'. Either include it or remove the dependency array.","line":223,"column":6,"nodeType":"ArrayExpression","endLine":223,"endColumn":47,"suggestions":[{"desc":"Update the dependencies array to be: [lockSegmentSelection, isSegmentRecorded, applyBoundaryEditability]","fix":{"range":[8560,8601],"text":"[lockSegmentSelection, isSegmentRecorded, applyBoundaryEditability]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'cleanupEventListeners'. Either include it or remove the dependency array.","line":551,"column":6,"nodeType":"ArrayExpression","endLine":551,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [cleanupEventListeners]","fix":{"range":[19973,19975],"text":"[cleanupEventListeners]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\user.removeFromOrg.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\user.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\waveformPeaks.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\waveformPeaks.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\wavesurferReady.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\crud\\wavesurferReady.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\BigDialog.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\BigDialog.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\BigDialogBp.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\DataChanges.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has a missing dependency: 'anySaving'. Either include it or remove the dependency array.","line":60,"column":45,"nodeType":"ArrayExpression","endLine":60,"endColumn":59,"suggestions":[{"desc":"Update the dependencies array to be: [anySaving]","fix":{"range":[2875,2889],"text":"[anySaving]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'memory'. Either include it or remove the dependency array.","line":73,"column":6,"nodeType":"ArrayExpression","endLine":73,"endColumn":19,"suggestions":[{"desc":"Update the dependencies array to be: [users, user, memory]","fix":{"range":[3579,3592],"text":"[users, user, memory]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'authenticated', 'dataDelay', and 'setBusy'. Either include them or remove the dependency array. You can also replace multiple useState variables with useReducer if 'setFirstRun' needs the current value of 'dataDelay'.","line":97,"column":6,"nodeType":"ArrayExpression","endLine":97,"endColumn":69,"suggestions":[{"desc":"Update the dependencies array to be: [remote, ctx, loadComplete, connected, firstRun, userDataDelay, dataDelay, authenticated, setBusy]","fix":{"range":[4417,4480],"text":"[remote, ctx, loadComplete, connected, firstRun, userDataDelay, dataDelay, authenticated, setBusy]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useCallback has missing dependencies: 'checkOnline', 'getGlobal', and 'setBusy'. Either include them or remove the dependency array.","line":117,"column":6,"nodeType":"ArrayExpression","endLine":117,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [checkOnline, getGlobal, remote, setBusy]","fix":{"range":[5234,5248],"text":"[checkOnline, getGlobal, remote, setBusy]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\DataProvider.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\ErrorBoundary.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\OrbitContext.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\OrbitContextProvider.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\OrbitContextProvider.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\PrivateRoute.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\SnackBar.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-refresh/only-export-components').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,57],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'open'. Either include it or remove the dependency array.","line":53,"column":6,"nodeType":"ArrayExpression","endLine":53,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [message, open]","fix":{"range":[1427,1436],"text":"[message, open]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable react-refresh/only-export-components */\nimport { useState, useEffect, Fragment } from 'react';\nimport { useGlobal } from '../context/useGlobal';\nimport {\n Snackbar as MuiSnackbar,\n IconButton,\n styled,\n BoxProps,\n Box,\n} from '@mui/material';\nimport CloseIcon from '@mui/icons-material/Close';\nimport MuiAlert, { AlertProps } from '@mui/material/Alert';\nimport { useMounted } from '../utils/useMounted';\nimport { useSnackBar } from './useSnackBar';\nexport { useSnackBar, AlertSeverity } from './useSnackBar';\n\nconst Alert = (props: AlertProps) => {\n return ;\n};\n\n// moved to ./useSnackBar\n\ninterface IProps {\n children: React.JSX.Element;\n}\nconst BarBox = styled(Box)(() => ({\n '& .MuiPaper-root': {\n alignItems: 'center',\n },\n}));\n\ninterface ISBProps {\n message: React.JSX.Element;\n}\n\nfunction SimpleSnackbar(props: ISBProps) {\n const isMounted = useMounted('snackbar');\n const { message } = props;\n const { messageReset } = useSnackBar();\n const [alert] = useGlobal('snackAlert'); //verified this is not used in a function 2/18/25\n const [open, setOpen] = useState(false);\n\n const handleClose = () => {\n messageReset();\n };\n\n useEffect(() => {\n const hasMessage = !!message && message.type !== Fragment;\n if (hasMessage !== open) {\n setOpen(hasMessage);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [message]);\n\n const CloseButton = () => (\n \n \n \n );\n\n return isMounted() && open ? (\n !alert ? (\n {message}}\n action={CloseButton()}\n />\n ) : (\n \n \n \n {message}\n \n \n \n )\n ) : (\n <>\n );\n}\n\nexport default function SnackBarProvider(props: IProps) {\n const { children } = props;\n const [message] = useGlobal('snackMessage');\n\n return (\n <>\n {children}\n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\VertListDnd.test.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'React' is defined but never used. Allowed unused vars must match /^_/u.","line":2,"column":8,"nodeType":null,"messageId":"unusedVar","endLine":2,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\VertListDnd.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\doDataChanges.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\processDataChanges.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\useOrbitData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\useSnackBar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\hoc\\withBucket.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\layout.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\main.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\Dialog.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\IExecResult.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\IdToken.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\SectionArray.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\activityState.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-refresh/only-export-components').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,57],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable react-refresh/only-export-components */\nimport { UninitializedRecord } from '@orbit/records';\nimport { IActivityStateStrings } from '.';\nimport { ActivityStates } from './activityStates';\n\nexport interface ActivityState extends UninitializedRecord {\n attributes: {\n state: string;\n sequencenum: string;\n };\n}\nexport default ActivityState;\n\nexport const localizeActivityState = (\n state: string,\n t: IActivityStateStrings\n) => {\n switch (state) {\n case ActivityStates.Approved:\n return t.approved;\n case ActivityStates.Done:\n return t.done;\n case ActivityStates.Incomplete:\n return t.incomplete;\n case ActivityStates.NeedsNewRecording:\n return t.needsNewRecording;\n case ActivityStates.NeedsNewTranscription:\n return t.needsNewTranscription;\n case ActivityStates.NoMedia:\n return t.noMedia;\n case ActivityStates.Reviewing:\n return t.reviewing;\n case ActivityStates.Synced:\n return t.done;\n case ActivityStates.TranscribeReady:\n return t.transcribeReady;\n case ActivityStates.Transcribed:\n return t.transcribed;\n case ActivityStates.Transcribing:\n return t.transcribing;\n }\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\activityStates.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\artifactCategory.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\artifactType.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\asrLang.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\audacityProject.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\baseModel.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\bible-brain-item.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\bible-project-lang.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\bible-resource.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\bible.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\bibleImage.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\bookName.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\bookRef.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\comment.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\countryAnalytics.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\dataChange.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\deleteItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\dialogMode.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\digestPreference.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\discussion.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\execa.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\graphic.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\group.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\groupMembership.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\index.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-refresh/only-export-components').","line":1,"column":1,"severity":1,"nodeType":null,"fix":{"range":[0,57],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable react-refresh/only-export-components */\nexport * from './organization';\nexport * from './organizationMembership';\nexport * from './group';\nexport * from './groupMembership';\nexport * from './integration';\nexport * from './invitation';\nexport * from './mediaDescription';\nexport * from './mediafile';\nexport * from './offlineProject';\nexport * from './project';\nexport * from './projectType';\nexport * from './plan';\nexport * from './planType';\nexport * from './section';\nexport * from './passage';\nexport * from './sectionPassage';\nexport * from './passageStateChange';\nexport * from './projectintegration';\nexport * from './user';\nexport * from './passageTypeEnum';\nexport * from './digestPreference';\nexport * from './role';\nexport * from './roleNames';\nexport * from './activityState';\nexport * from './activityStates';\nexport * from './deleteItem';\nexport * from './vproject';\nexport * from './state';\nexport * from '../store/book/types';\nexport * from '../store/localization/types';\nexport * from '../store/localization/model';\nexport * from '../store/orbit/types';\nexport * from '../store/upload/types';\nexport * from '../store/paratext/types';\nexport * from '../store/importexport/types';\nexport * from '../store/auth/types';\nexport * from './dialogMode';\nexport * from './Dialog';\nexport * from './optionType';\nexport * from './offlineProject';\nexport * from './audacityProject';\nexport * from './execa';\nexport * from './token';\nexport * from './sheet';\nexport * from './wfSaveRec';\nexport * from './orgData';\nexport * from './workflowStep';\nexport * from './artifactCategory';\nexport * from './artifactType';\nexport * from './orgKeyterm';\nexport * from './orgKeytermTarget';\nexport * from './orgWorkflowStep';\nexport * from './discussion';\nexport * from './comment';\nexport * from './resource';\nexport * from './sectionResource';\nexport * from './sectionResourceUser';\nexport * from './stepComplete';\nexport * from './keyTerm';\nexport * from './sharedResource';\nexport * from './sharedResourceReference';\nexport * from './bookRef';\nexport * from './graphic';\nexport * from './bibleImage';\nexport * from './bible';\nexport * from './organizationBible';\nexport * from './paratextProject';\nexport * from './intellectualProperty';\nexport * from './vwchecksum';\nexport * from './userAnalytics';\nexport * from './countryAnalytics';\nexport * from './IExecResult';\nexport * from './SectionArray';\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\integration.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\intellectualProperty.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\invitation.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\keyTerm.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\main-api.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\mediaDescription.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\mediafile.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\offlineProject.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\optionType.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\orgData.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\orgKeyterm.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\orgKeytermTarget.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\orgWorkflowStep.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\organization.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\organizationBible.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\organizationMembership.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\organizationScheme.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\organizationSchemeStep.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\paratextProject.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\passage.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\passageStateChange.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\passageType.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\passageTypeEnum.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\plan.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\planType.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\projData.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\project.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\projectType.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\projectintegration.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\resource.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\role.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\roleNames.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\section.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\sectionPassage.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\sectionResource.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\sectionResourceUser.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\sharedResource.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\sharedResourceReference.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\sheet.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\stat.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\state.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\stepComplete.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\token.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\user.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\userAnalytics.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\vproject.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\vwbiblebrainbible.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\vwbiblebrainlanguage.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\vwchecksum.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\wfSaveRec.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\model\\workflowStep.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\Access.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'authSessionCleared', 'checkOnline', 'handleGoOnline', 'handleSelect', 'loginWithRedirect', 'resetProject', 'tokenCtx.state', and 'user'. Either include them or remove the dependency array.","line":322,"column":6,"nodeType":"ArrayExpression","endLine":322,"endColumn":67,"suggestions":[{"desc":"Update the dependencies array to be: [accessToken, isAuthenticated, offline, expiresAt, isLoading, resetProject, checkOnline, tokenCtx.state, user, authSessionCleared, loginWithRedirect, handleSelect, handleGoOnline]","fix":{"range":[10210,10271],"text":"[accessToken, isAuthenticated, offline, expiresAt, isLoading, resetProject, checkOnline, tokenCtx.state, user, authSessionCleared, loginWithRedirect, handleSelect, handleGoOnline]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'curUser', 'handleGoOnline', 'offline', 'selectedUser', 'setLanguage', 'setOffline', 'tokenCtx.state', and 'whichUsers'. Either include them or remove the dependency array.","line":381,"column":6,"nodeType":"ArrayExpression","endLine":381,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [curUser, handleGoOnline, offline, selectedUser, setLanguage, setOffline, tokenCtx.state, users, whichUsers]","fix":{"range":[12633,12640],"text":"[curUser, handleGoOnline, offline, selectedUser, setLanguage, setOffline, tokenCtx.state, users, whichUsers]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'handleGoOnline' and 'handleSelect'. Either include them or remove the dependency array.","line":392,"column":6,"nodeType":"ArrayExpression","endLine":392,"endColumn":15,"suggestions":[{"desc":"Update the dependencies array to be: [curUser, handleGoOnline, handleSelect]","fix":{"range":[12961,12970],"text":"[curUser, handleGoOnline, handleSelect]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'handleGoOnline' and 'tokenCtx.state'. Either include them or remove the dependency array.","line":420,"column":6,"nodeType":"ArrayExpression","endLine":420,"endColumn":38,"suggestions":[{"desc":"Update the dependencies array to be: [expiresAt, whichUsers, offline, tokenCtx.state, handleGoOnline]","fix":{"range":[13673,13705],"text":"[expiresAt, whichUsers, offline, tokenCtx.state, handleGoOnline]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\Buggy.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\CreateProfile.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\ElectronImport.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\EmailUnverified.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getAccessTokenSilently', 'isMounted', and 'setAuthSession'. Either include them or remove the dependency array.","line":88,"column":6,"nodeType":"ArrayExpression","endLine":88,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [getAccessTokenSilently, isMounted, setAuthSession, user]","fix":{"range":[2901,2907],"text":"[getAccessTokenSilently, isMounted, setAuthSession, user]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\Loading.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'authenticated', 'coordinator', 'errorReporter', 'fetchLocalization', 'fetchOrbitData', 'fingerprint', 'forceDataChanges', 'getOfflineProject', 'isDeveloper', 'offlineSetup', 'setExpireAt', 'setLanguage', 'setOrbitRetries', 'setProjectsLoaded', 'setUser', 'showMessage', and 'tokenCtx'. Either include them or remove the dependency array.","line":247,"column":6,"nodeType":"ArrayExpression","endLine":247,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [accessToken, authenticated, coordinator, errorReporter, fetchLocalization, fetchOrbitData, fingerprint, forceDataChanges, getOfflineProject, isDeveloper, offline, offlineSetup, setExpireAt, setLanguage, setOrbitRetries, setProjectsLoaded, setUser, showMessage, tokenCtx]","fix":{"range":[8629,8651],"text":"[accessToken, authenticated, coordinator, errorReporter, fetchLocalization, fetchOrbitData, fingerprint, forceDataChanges, getOfflineProject, isDeveloper, offline, offlineSetup, setExpireAt, setLanguage, setOrbitRetries, setProjectsLoaded, setUser, showMessage, tokenCtx]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'setLanguage'. Either include it or remove the dependency array.","line":264,"column":6,"nodeType":"ArrayExpression","endLine":264,"endColumn":39,"suggestions":[{"desc":"Update the dependencies array to be: [orbitFetchResults, memory, user, setLanguage]","fix":{"range":[9039,9072],"text":"[orbitFetchResults, memory, user, setLanguage]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'InviteUser', 'LoadComplete', 'backup', 'coordinator', 'doOrbitError', 'handleAuthFailure', 'profile', 'remote', 'setCompleted', 'setOrbitRetries', 'setProjectsLoaded', and 't.loadDataOffline'. Either include them or remove the dependency array.","line":456,"column":6,"nodeType":"ArrayExpression","endLine":456,"endColumn":54,"suggestions":[{"desc":"Update the dependencies array to be: [syncComplete, orbitFetchResults, orbitErrorMsg, profile, remote, InviteUser, setCompleted, coordinator, doOrbitError, t.loadDataOffline, setOrbitRetries, LoadComplete, handleAuthFailure, backup, setProjectsLoaded]","fix":{"range":[15565,15613],"text":"[syncComplete, orbitFetchResults, orbitErrorMsg, profile, remote, InviteUser, setCompleted, coordinator, doOrbitError, t.loadDataOffline, setOrbitRetries, LoadComplete, handleAuthFailure, backup, setProjectsLoaded]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'handleAuthFailure'. Either include it or remove the dependency array.","line":492,"column":6,"nodeType":"ArrayExpression","endLine":492,"endColumn":26,"suggestions":[{"desc":"Update the dependencies array to be: [offline, expiresAt, handleAuthFailure]","fix":{"range":[16402,16422],"text":"[offline, expiresAt, handleAuthFailure]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\Logout.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'fetchLocalization', 'handleLogout', 'isDeveloper', and 'setLanguage'. Either include them or remove the dependency array.","line":61,"column":6,"nodeType":"ArrayExpression","endLine":61,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [fetchLocalization, handleLogout, isDeveloper, setLanguage]","fix":{"range":[2298,2300],"text":"[fetchLocalization, handleLogout, isDeveloper, setLanguage]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\NavRoutes.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\PassageDetail.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\PassageDetail.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'prjId', 'projType', 'setProjectType', 'setUrlContext', and 'user'. Either include them or remove the dependency array.","line":210,"column":6,"nodeType":"ArrayExpression","endLine":210,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [prjId, projType, setProjectType, setUrlContext, user]","fix":{"range":[8393,8395],"text":"[prjId, projType, setProjectType, setUrlContext, user]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\PlanScreen.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has missing dependencies: 'prjId', 'projType', 'setProjectType', 'setUrlContext', and 'user'. Either include them or remove the dependency array.","line":32,"column":6,"nodeType":"ArrayExpression","endLine":32,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [prjId, projType, setProjectType, setUrlContext, user]","fix":{"range":[1374,1376],"text":"[prjId, projType, setProjectType, setUrlContext, user]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'setUrlContext'. Either include it or remove the dependency array.","line":37,"column":6,"nodeType":"ArrayExpression","endLine":37,"endColumn":13,"suggestions":[{"desc":"Update the dependencies array to be: [prjId, setUrlContext]","fix":{"range":[1503,1510],"text":"[prjId, setUrlContext]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'view'. Either include it or remove the dependency array.","line":43,"column":6,"nodeType":"ArrayExpression","endLine":43,"endColumn":29,"suggestions":[{"desc":"Update the dependencies array to be: [project, organization, view]","fix":{"range":[1696,1719],"text":"[project, organization, view]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\ProjectsScreen.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setHome' and 'startClear'. Either include them or remove the dependency array.","line":61,"column":6,"nodeType":"ArrayExpression","endLine":61,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [setHome, startClear]","fix":{"range":[2834,2836],"text":"[setHome, startClear]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'memory' and 'navigate'. Either include them or remove the dependency array.","line":182,"column":6,"nodeType":"ArrayExpression","endLine":182,"endColumn":28,"suggestions":[{"desc":"Update the dependencies array to be: [plan, pathname, home, memory, navigate]","fix":{"range":[6433,6455],"text":"[plan, pathname, home, memory, navigate]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\ScriptureBurrito.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook React.useEffect has a missing dependency: 'getOrgDefault'. Either include it or remove the dependency array.","line":75,"column":6,"nodeType":"ArrayExpression","endLine":75,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, teamId]","fix":{"range":[2664,2672],"text":"[getOrgDefault, teamId]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\SwitchTeams.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\TeamScreen.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'setHome' and 'startClear'. Either include them or remove the dependency array.","line":41,"column":6,"nodeType":"ArrayExpression","endLine":41,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [setHome, startClear]","fix":{"range":[1886,1888],"text":"[setHome, startClear]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'memory', 'resetProject', and 'setProject'. Either include them or remove the dependency array.","line":72,"column":6,"nodeType":"ArrayExpression","endLine":72,"endColumn":48,"suggestions":[{"desc":"Update the dependencies array to be: [project, projType, isOffline, plan, home, memory, setProject, resetProject]","fix":{"range":[2890,2932],"text":"[project, projType, isOffline, plan, home, memory, setProject, resetProject]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\TermsContent.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\Welcome.tsx","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'checkOnline', 'checkUsers', 'dispatch', 'fetchLocalization', 'isDeveloper', 'search', and 'setLanguage'. Either include them or remove the dependency array.","line":219,"column":6,"nodeType":"ArrayExpression","endLine":219,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [checkOnline, checkUsers, dispatch, fetchLocalization, isDeveloper, search, setLanguage]","fix":{"range":[6898,6900],"text":"[checkOnline, checkUsers, dispatch, fetchLocalization, isDeveloper, search, setLanguage]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'checkUsers', 'dispatch', 'importComplete', 'setBusy', and 'userTypes'. Either include them or remove the dependency array.","line":230,"column":6,"nodeType":"ArrayExpression","endLine":230,"endColumn":20,"suggestions":[{"desc":"Update the dependencies array to be: [checkUsers, dispatch, importComplete, importStatus, setBusy, userTypes]","fix":{"range":[7261,7275],"text":"[checkUsers, dispatch, importComplete, importStatus, setBusy, userTypes]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\__mocks__\\NavRoutes.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\accessActions.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\routes\\privacyContent.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\schema.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\selector\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\selector\\localize.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\selector\\localize.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\selector\\selectors.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\serializers\\DateAndNullSerializer.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\serializers\\getSerializer.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\serializers\\serializersFor.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\AxiosStatus.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\auth\\actions.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\auth\\authCleanState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\auth\\reducers.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\auth\\types.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\book\\actions.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\book\\bookCleanState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\book\\reducers.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\book\\types.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\importexport\\actions.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\importexport\\copyProject.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":37,"column":25,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":37,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\importexport\\electronExport.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\importexport\\exportCleanState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\importexport\\exportTableRecs.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\importexport\\isAttachedMediaFile.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\importexport\\isAttachedMediaFile.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\importexport\\projectDataExport.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\importexport\\projectDataExport.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\importexport\\reducers.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\importexport\\types.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\index.tsx","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-refresh/only-export-components').","line":46,"column":1,"severity":1,"nodeType":null,"fix":{"range":[1384,1441],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import {\n applyMiddleware,\n combineReducers,\n legacy_createStore as createStore,\n type Store,\n type AnyAction,\n} from 'redux';\nimport bookReducer from './book/reducers';\nimport localizationReducer from './localization/reducers';\nimport orbitReducer from './orbit/reducers';\nimport uploadReducer from './upload/reducers';\nimport paratextReducer from './paratext/reducers';\nimport exportReducer from './importexport/reducers';\nimport authReducer from './auth/reducers';\n\nimport { composeWithDevTools } from '@redux-devtools/extension';\nimport { thunk, ThunkMiddleware } from 'redux-thunk';\n\nconst appReducer = combineReducers({\n strings: localizationReducer,\n books: bookReducer,\n orbit: orbitReducer,\n upload: uploadReducer,\n paratext: paratextReducer,\n importexport: exportReducer,\n auth: authReducer,\n});\n\nexport type AppState = ReturnType;\nexport type AppAction = AnyAction;\nexport type AppStore = Store;\nexport type AppDispatch = AppStore['dispatch'];\n\nexport default function configureStore(): AppStore {\n const middleWareEnhancer = applyMiddleware(\n thunk as unknown as ThunkMiddleware\n );\n // Disambiguate overload by providing explicit undefined preloaded state\n const store = createStore(\n appReducer,\n undefined,\n composeWithDevTools(middleWareEnhancer)\n );\n return store;\n}\n/* eslint-disable react-refresh/only-export-components */\nexport * from './book/actions';\nexport * from './localization/actions';\nexport * from './orbit/actions';\nexport * from './upload/actions';\nexport * from './paratext/actions';\nexport * from './importexport/actions';\nexport * from './auth/actions';\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\localization\\actions.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\localization\\model.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\localization\\reducers.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\localization\\types.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\orbit\\actions.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\orbit\\orbitCleanState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\orbit\\reducers.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\orbit\\types.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\paratext\\actions.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\paratext\\paratextCleanState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\paratext\\reducers.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\paratext\\types.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\actions.duplicatePendingUpload.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":126,"column":21,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":126,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":127,"column":21,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":127,"endColumn":53,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":134,"column":19,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":134,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":134,"column":47,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":134,"endColumn":63,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\actions.pendingRetry.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":62,"column":24,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":62,"endColumn":44,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":606,"column":26,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":606,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":612,"column":21,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":612,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\actions.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\actions.uploadBusy.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":44,"column":24,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":44,"endColumn":44,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\completePendingUploadRetry.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\completePendingUploadRetry.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\pendingMediaUploads.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\pendingMediaUploads.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\pendingProjectResourceConfig.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\pendingProjectResourceConfig.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\pendingUploadRetryGaps.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\reducers.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\restoreAfterPendingUpload.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\restoreAfterPendingUpload.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\types.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\uploadRetry.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\uploadRetry.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\uploadTerminalMessages.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\withPendingRetryBusyRelease.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\store\\upload\\withPendingRetryBusyRelease.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\theme.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\ReactIsInDevelopmentMode.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\__tests__\\parseBurritoMetadata.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\addPt.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\appPath.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\audioBufferToWavBlob.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\audioPlayback.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\audioPlayback.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\axios.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\bcvKey.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\blobToBase64.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\burritoConversion.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":28,"column":12,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":28,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\burritoConversion.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\burritoMediaFileStem.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\burritoMediaFileStem.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\camel2Title.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\carefulSpeechSegmentColors.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\carefulSpeechSegmentColors.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":31,"column":3,"severity":1,"nodeType":null,"fix":{"range":[1144,1205],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { type RefObject } from 'react';\nimport { type ApplyRegionColor } from '../crud/useWavesurferRegions';\n\n/** Waveform colors for Careful Speech (completed / current / pending). */\n\nexport const CAREFUL_SPEECH_COMPLETED_RGBA = 'rgba(76, 175, 80, 0.35)';\nexport const CAREFUL_SPEECH_CURRENT_RGBA = 'rgba(255, 235, 59, 0.5)';\nexport const CAREFUL_SPEECH_PENDING_RGBA = 'rgba(158, 158, 158, 0.22)';\n\nexport const getCarefulSpeechCompletedColor = () =>\n CAREFUL_SPEECH_COMPLETED_RGBA;\nexport const getCarefulSpeechCurrentColor = () => CAREFUL_SPEECH_CURRENT_RGBA;\nexport const getCarefulSpeechPendingColor = () => CAREFUL_SPEECH_PENDING_RGBA;\n\nexport interface ICarefulSpeechColorStatus {\n currentIndex: number;\n isCompleted: (regionIndex: number) => boolean;\n}\n\nexport const getCarefulSpeechRegionBaseColor = (\n regionIndex: number,\n status: ICarefulSpeechColorStatus\n) => {\n if (status.isCompleted(regionIndex)) return getCarefulSpeechCompletedColor();\n return getCarefulSpeechPendingColor();\n};\n\nexport const createCarefulSpeechApplyRegionColor = (\n statusRef: RefObject\n): ApplyRegionColor => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n return (role, regionIndex, _regionCount) => {\n if (role === 'current') return getCarefulSpeechCurrentColor();\n if (role === 'new') return getCarefulSpeechPendingColor();\n const status = statusRef.current;\n if (!status) return getCarefulSpeechPendingColor();\n return getCarefulSpeechRegionBaseColor(regionIndex, status);\n };\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\clauseSplitSilence.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\clauseSplitSilence.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\cleanClipboard.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\cleanFileName.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\cleanFileName.ts","messages":[],"suppressedMessages":[{"ruleId":"no-control-regex","severity":2,"message":"Unexpected control character(s) in regular expression: \\x00, \\x1f.","line":14,"column":26,"nodeType":"Literal","messageId":"unexpected","endLine":14,"endColumn":65,"suppressions":[{"kind":"directive","justification":"matches Path.GetInvalidFileNameChars()"}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\compressedImageDisplayUrl.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\compressedImageDisplayUrl.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\contentType.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\createFolder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\currentDateTime.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\dataGridLocale.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\dataPath.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":31,"column":12,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":31,"endColumn":33,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\dataPath.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\dateOrTime.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\decodeAudioData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\eqSet.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\evictMediaCache.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":47,"column":12,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":47,"endColumn":40,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\evictMediaCache.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\execFolder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\exitElectronApp.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\fileJson.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\filterFilesBySizeLimit.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\fontFamilyName.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\forceLogin.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\generateUUID.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\getAudacityExe.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\getFingerprint.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\getLocalFile.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\getMediaExt.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\getMediaExt.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\getRefWidth.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\getRegVal.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\getScrollbarWidth.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\getUrlNameAndExt.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\getWhereis.ts","messages":[],"suppressedMessages":[{"ruleId":"no-unsafe-optional-chaining","severity":2,"message":"Unsafe usage of optional chaining. If it short-circuits with 'undefined' the evaluation will throw TypeError.","line":12,"column":41,"nodeType":"ChainExpression","messageId":"unsafeOptionalChain","endLine":12,"endColumn":50,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\handleUnauthorized.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\handleUnauthorized.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\hasAuacity.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\hasPython.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\httpError.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\ignoreVs.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\infoMsg.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\insertAtCursor.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\integrationSlug.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\isAudioLoadAbort.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\isAudioLoadAbort.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\isMobileWidth.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\isUrl.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\isVisual.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\jsonParse.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\langName.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\langTag.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\launch.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\launch.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\launchAudacity.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\libraryGraphicToCompressedImages.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\libraryGraphicToCompressedImages.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\linuxProgPath.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\loadBlob.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\loadBlob.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\localUserKey.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\localeDefault.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\localizeGrid.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'parameters' is defined but never used. Allowed unused args must match /^_/u.","line":56,"column":12,"nodeType":null,"messageId":"unusedVar","endLine":56,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\localizeProjectTag.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\localizeRole.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\logErrorService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\lookupBook.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\makeAbbr.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\markVersesEditReference.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\markVersesEditReference.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\markVersesPassageVerses.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\markVersesPassageVerses.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\markVersesSegmentColors.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\markVersesSegmentColors.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\markVersesTableReconstruction.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\markVersesTableReconstruction.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\markVersesUndoStack.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\markVersesUndoStack.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\mediaLanguage.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\mimeTypes.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\missingDownloadCompletion.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\missingDownloadCompletion.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\namedSegments.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\needItfSync.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\needItfSync.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\needsStepNavigationConfirm.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\needsStepNavigationConfirm.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\networkRetry.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\networkRetry.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\onlyUnique.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\orbitStrategyErrors.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\orbitStrategyErrors.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\pad2.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\pad3.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\paratextPath.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\parseBurritoMetadata.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\parseQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\passageDefaultFilename.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\perf.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'react-hooks/refs').","line":22,"column":1,"severity":1,"nodeType":null,"fix":{"range":[973,1010],"text":" "}}],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies.","line":179,"column":6,"nodeType":"Identifier","endLine":179,"endColumn":10,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'deps', 'effect', and 'label'. Either include them or remove the dependency array. If 'effect' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":179,"column":6,"nodeType":"Identifier","endLine":179,"endColumn":10,"suggestions":[{"desc":"Update the dependencies array to be: [deps, effect, label]","fix":{"range":[5687,5691],"text":"[deps, effect, label]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies.","line":202,"column":6,"nodeType":"Identifier","endLine":202,"endColumn":10,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useMemo has missing dependencies: 'deps', 'factory', and 'label'. Either include them or remove the dependency array. If 'factory' changes too often, find the parent component that defines it and wrap that definition in useCallback.","line":202,"column":6,"nodeType":"Identifier","endLine":202,"endColumn":10,"suggestions":[{"desc":"Update the dependencies array to be: [deps, factory, label]","fix":{"range":[6317,6321],"text":"[deps, factory, label]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/**\n * Lightweight, opt-in performance instrumentation.\n *\n * Goal: find out why the app becomes unresponsive — which components re-render\n * in storms, which effects/memos are slow, which global-state keys churn, and\n * what long-tasks block the main thread (so clicks/dialogs feel delayed).\n *\n * ── Turn it on (in the app's devtools console) ─────────────────────────────\n * aptPerf.on() // enables + reloads\n * or set localStorage 'perfDebug' = '1' and reload.\n *\n * ── Reproduce the problem, then get a report ───────────────────────────────\n * aptPerf.report() // prints tables + copies a text report to clipboard\n * aptPerf.reset() // zero the counters (e.g. right before a repro step)\n * aptPerf.auto(5000) // print a compact summary every 5s (0 to stop)\n * aptPerf.off() // disable + reload\n *\n * Everything is a no-op with near-zero cost when disabled, so it is safe to\n * leave the instrumentation calls in place.\n */\n\n/* eslint-disable react-hooks/refs */\n// This is an opt-in debug utility: it intentionally reads refs across renders\n// (to compare previous vs current values) and logs to the console.\nimport { useEffect, useMemo, useRef } from 'react';\n\nconst FLAG = 'perfDebug';\n\nlet enabled = false;\ntry {\n enabled =\n typeof localStorage !== 'undefined' && localStorage.getItem(FLAG) === '1';\n} catch {\n enabled = false;\n}\n\nexport const perfEnabled = (): boolean => enabled;\n\nconst now = (): number =>\n typeof performance !== 'undefined' ? performance.now() : 0;\n\ntype Kind = 'render' | 'effect' | 'memo' | 'global' | 'longtask' | 'fn';\n\ninterface Stat {\n kind: Kind;\n label: string;\n count: number;\n totalMs: number;\n maxMs: number;\n lastTs: number;\n /** recent fire times (perf clock) for burst/storm detection */\n recent: number[];\n /** for effects/memos: how many times a given dep index was the one that changed */\n depChanges?: Record;\n}\n\nconst registry = new Map();\nconst RECENT_WINDOW_MS = 1000;\nconst RECENT_MAX = 200;\n\nconst keyFor = (kind: Kind, label: string) => `${kind}::${label}`;\n\nconst stat = (kind: Kind, label: string): Stat => {\n const k = keyFor(kind, label);\n let s = registry.get(k);\n if (!s) {\n s = { kind, label, count: 0, totalMs: 0, maxMs: 0, lastTs: 0, recent: [] };\n registry.set(k, s);\n }\n return s;\n};\n\nconst record = (kind: Kind, label: string, ms: number, depIdx?: number) => {\n const s = stat(kind, label);\n const t = now();\n s.count += 1;\n s.totalMs += ms;\n if (ms > s.maxMs) s.maxMs = ms;\n s.lastTs = t;\n s.recent.push(t);\n if (s.recent.length > RECENT_MAX) s.recent.shift();\n if (depIdx !== undefined && depIdx >= 0) {\n if (!s.depChanges) s.depChanges = {};\n s.depChanges[depIdx] = (s.depChanges[depIdx] ?? 0) + 1;\n }\n};\n\n/** peak fires within any RECENT_WINDOW_MS sliding window (storm intensity) */\nconst peakBurst = (s: Stat): number => {\n if (s.recent.length === 0) return 0;\n let peak = 0;\n let start = 0;\n for (let end = 0; end < s.recent.length; end++) {\n while (s.recent[end] - s.recent[start] > RECENT_WINDOW_MS) start++;\n peak = Math.max(peak, end - start + 1);\n }\n return peak;\n};\n\n// ── Public recording helpers (used by non-hook call sites) ──────────────────\n\n/** Record an explicit global-state key mutation (called from useGlobal setter). */\nexport const perfRecordGlobalSet = (prop: string): void => {\n if (!enabled) return;\n record('global', prop, 0);\n};\n\n/** Record a pre-measured duration (for async work you time yourself). */\nexport const perfRecordMs = (label: string, ms: number): void => {\n if (!enabled) return;\n record('fn', label, ms);\n};\n\n/** Time an arbitrary function and record it under `label`. */\nexport const perfTime = (label: string, fn: () => T): T => {\n if (!enabled) return fn();\n const t = now();\n try {\n return fn();\n } finally {\n record('fn', label, now() - t);\n }\n};\n\n// ── Hooks ───────────────────────────────────────────────────────────────────\n\n/**\n * Count renders of a component and detect render storms.\n * Drop `useRenderProfiler('MyComponent')` at the top of a component body.\n */\nexport const useRenderProfiler = (label: string): void => {\n const last = useRef(0);\n if (!enabled) return;\n const t = now();\n const delta = last.current ? t - last.current : 0;\n last.current = t;\n // ms field here stores inter-render gap so maxMs = longest gap (not useful);\n // we mainly want count + burst, so store 0 for time.\n record('render', label, 0);\n // stash the tightest gap in depChanges[0] as a proxy (optional)\n if (delta > 0 && delta < 16) {\n const s = stat('render', label);\n s.depChanges = s.depChanges ?? {};\n s.depChanges[0] = (s.depChanges[0] ?? 0) + 1; // renders <16ms apart (back-to-back)\n }\n};\n\nconst changedDepIndex = (\n prev: readonly any[] | undefined,\n next: readonly any[]\n): number => {\n if (!prev) return -1;\n const len = Math.max(prev.length, next.length);\n for (let i = 0; i < len; i++) {\n if (!Object.is(prev[i], next[i])) return i;\n }\n return -1;\n};\n\n/**\n * Drop-in replacement for useEffect that times the effect body and records\n * which dependency index changed to trigger it.\n */\nexport const useTimedEffect = (\n label: string,\n effect: () => void | (() => void),\n deps: readonly any[]\n): void => {\n const prev = useRef(undefined);\n useEffect(() => {\n if (!enabled) return effect();\n const depIdx = changedDepIndex(prev.current, deps);\n prev.current = deps;\n const t = now();\n const cleanup = effect();\n record('effect', label, now() - t, depIdx);\n return cleanup;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n};\n\n/**\n * Drop-in replacement for useMemo that times the factory and records which\n * dependency changed to trigger the recompute.\n */\nexport const useTimedMemo = (\n label: string,\n factory: () => T,\n deps: readonly any[]\n): T => {\n const prev = useRef(undefined);\n\n return useMemo(() => {\n if (!enabled) return factory();\n const depIdx = changedDepIndex(prev.current, deps);\n prev.current = deps;\n const t = now();\n const value = factory();\n record('memo', label, now() - t, depIdx);\n return value;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n};\n\n/**\n * Log which *named* dependency changed between renders — the fastest way to\n * find \"why is this component re-rendering so much\". Pass an object of the\n * props/values you suspect: useWhyRender('UserMenu', { user, users, org }).\n */\nexport const useWhyRender = (\n label: string,\n watched: Record\n): void => {\n const prev = useRef | undefined>(undefined);\n if (!enabled) return;\n const before = prev.current;\n prev.current = { ...watched };\n if (!before) return;\n const changed: string[] = [];\n for (const k of Object.keys(watched)) {\n if (!Object.is(before[k], watched[k])) changed.push(k);\n }\n if (changed.length) {\n for (const k of changed) record('render', `${label}⇐${k}`, 0);\n } else {\n // re-rendered but none of the watched values changed → parent/context churn\n record('render', `${label}⇐(context/parent)`, 0);\n }\n};\n\n// ── Long-task observer (why do clicks/dialogs feel delayed?) ────────────────\n\nlet longTaskObserver: PerformanceObserver | undefined;\nconst startLongTaskObserver = () => {\n if (\n !enabled ||\n longTaskObserver ||\n typeof PerformanceObserver === 'undefined'\n )\n return;\n try {\n longTaskObserver = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n record('longtask', 'main-thread-block', entry.duration);\n if (entry.duration >= 200) {\n console.warn(\n `[aptPerf] LONG TASK ${Math.round(entry.duration)}ms blocked the main thread`\n );\n }\n }\n });\n longTaskObserver.observe({ entryTypes: ['longtask'] });\n } catch {\n /* longtask not supported */\n }\n};\n\n// ── Reporting ───────────────────────────────────────────────────────────────\n\nconst fmt = (n: number) => Math.round(n * 10) / 10;\n\nconst buildReport = (): string => {\n const lines: string[] = [];\n const all = [...registry.values()];\n\n const section = (\n title: string,\n kinds: Kind[],\n sortBy: (s: Stat) => number,\n cols: (s: Stat) => Record\n ) => {\n const rows = all\n .filter((s) => kinds.includes(s.kind))\n .sort((a, b) => sortBy(b) - sortBy(a))\n .slice(0, 40);\n if (!rows.length) return;\n lines.push(`\\n## ${title}`);\n for (const s of rows) {\n const c = cols(s);\n lines.push(\n ' ' +\n Object.entries(c)\n .map(([k, v]) => `${k}=${v}`)\n .join(' ')\n );\n }\n // also print as a table for interactive inspection\n\n console.log(`%c${title}`, 'font-weight:bold');\n\n console.table(rows.map((s) => cols(s)));\n };\n\n section(\n 'RENDERS (by count) — look for storms: high count + high peak/sec',\n ['render'],\n (s) => s.count,\n (s) => ({\n component: s.label,\n renders: s.count,\n 'peak/sec': peakBurst(s),\n 'back2back<16ms': s.depChanges?.[0] ?? 0,\n })\n );\n\n section(\n 'EFFECTS (by total ms) — slow or too-frequent effects',\n ['effect'],\n (s) => s.totalMs,\n (s) => ({\n effect: s.label,\n runs: s.count,\n totalMs: fmt(s.totalMs),\n maxMs: fmt(s.maxMs),\n 'peak/sec': peakBurst(s),\n hotDep: s.depChanges\n ? Object.entries(s.depChanges).sort((a, b) => b[1] - a[1])[0]?.[0]\n : '',\n })\n );\n\n section(\n 'MEMOS (by total ms) — expensive or thrashing memos',\n ['memo'],\n (s) => s.totalMs,\n (s) => ({\n memo: s.label,\n recomputes: s.count,\n totalMs: fmt(s.totalMs),\n maxMs: fmt(s.maxMs),\n 'peak/sec': peakBurst(s),\n hotDep: s.depChanges\n ? Object.entries(s.depChanges).sort((a, b) => b[1] - a[1])[0]?.[0]\n : '',\n })\n );\n\n section(\n 'GLOBAL STATE writes (by count) — cascade drivers',\n ['global'],\n (s) => s.count,\n (s) => ({ key: s.label, writes: s.count, 'peak/sec': peakBurst(s) })\n );\n\n section(\n 'PLAIN FUNCTIONS (by total ms)',\n ['fn'],\n (s) => s.totalMs,\n (s) => ({\n fn: s.label,\n calls: s.count,\n totalMs: fmt(s.totalMs),\n maxMs: fmt(s.maxMs),\n })\n );\n\n const lt = registry.get(keyFor('longtask', 'main-thread-block'));\n if (lt) {\n lines.push(\n `\\n## LONG TASKS (main-thread blocks ≥50ms — cause of click/dialog delay)`\n );\n lines.push(\n ` count=${lt.count} totalMs=${fmt(lt.totalMs)} worstMs=${fmt(lt.maxMs)} peak/sec=${peakBurst(lt)}`\n );\n }\n\n const header =\n `# aptPerf report @ ${new Date().toISOString()}\\n` +\n `enabled=${enabled} tracked=${registry.size} labels`;\n return header + '\\n' + lines.join('\\n') + '\\n';\n};\n\nconst report = (): string => {\n const text = buildReport();\n\n console.log(text);\n try {\n // best-effort clipboard copy so the report is easy to paste back\n (navigator as any)?.clipboard?.writeText?.(text);\n\n console.log('%c[aptPerf] report copied to clipboard', 'color:green');\n } catch {\n /* clipboard unavailable */\n }\n return text;\n};\n\nconst reset = () => {\n registry.clear();\n\n console.log('[aptPerf] counters reset');\n};\n\nlet autoTimer: ReturnType | undefined;\nconst auto = (ms: number) => {\n if (autoTimer) {\n clearInterval(autoTimer);\n autoTimer = undefined;\n }\n if (ms > 0) {\n autoTimer = setInterval(() => {\n const renders = [...registry.values()]\n .filter((s) => s.kind === 'render')\n .sort((a, b) => b.count - a.count)\n .slice(0, 5)\n .map((s) => `${s.label}:${s.count}`)\n .join(' ');\n\n console.log(`[aptPerf] top renders — ${renders}`);\n }, ms);\n }\n};\n\nconst on = () => {\n try {\n localStorage.setItem(FLAG, '1');\n } catch {\n /* ignore */\n }\n location.reload();\n};\nconst off = () => {\n try {\n localStorage.removeItem(FLAG);\n } catch {\n /* ignore */\n }\n location.reload();\n};\n\n// Expose a console API regardless of enabled state so `aptPerf.on()` works.\nif (typeof window !== 'undefined') {\n (window as any).aptPerf = {\n on,\n off,\n report,\n reset,\n auto,\n enabled: () => enabled,\n _registry: registry,\n };\n}\n\nif (enabled) {\n startLongTaskObserver();\n\n console.log(\n '%c[aptPerf] instrumentation ON — reproduce the issue, then run aptPerf.report()',\n 'color:orange;font-weight:bold'\n );\n}\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\phraseSegmentUndoStack.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\phraseSegmentUndoStack.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\positiveWholeOnly.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\prettySegment.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\rangeAdd.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\readItfEmbeddedProject.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\recoverBackupSyncFail.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\recoverBackupSyncFail.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\refMatch.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars').","line":7,"column":3,"severity":1,"nodeType":null,"fix":{"range":[195,256],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"export const refMatch = (ref: string): RegExpExecArray | null => {\n const m =\n /^([0-9]+)[:.]([0-9]+[a-e]?)-?([0-9]*[a-e]?)[:.]?([0-9]*[a-e]?)$/g.exec(\n ref\n );\n if (!m) return m;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [_, chapter, verseStart, arg3, verseEnd] = m;\n if (verseEnd) {\n if (parseInt(arg3 || '0') !== parseInt(chapter || '0') + 1) return null;\n return m;\n } else if (arg3) {\n // Same verse, letter-suffix range (e.g. 1:22a-b = verse 22, parts a through b).\n const sameVerseLetterEnd =\n /^[a-e]$/i.test(arg3) && /^(\\d+)([a-e])$/i.exec(verseStart || '');\n if (sameVerseLetterEnd) {\n const [, , startLetter] = sameVerseLetterEnd;\n const endLetter = arg3.toLowerCase();\n if (endLetter <= startLetter.toLowerCase()) return null;\n return m;\n }\n const vBeg = parseInt(verseStart || '');\n const vEnd = parseInt(arg3 || '');\n if (Number.isNaN(vBeg) || Number.isNaN(vEnd)) return null;\n if (vEnd < vBeg) return null;\n else if (vBeg === vEnd && arg3 <= (verseStart || '')) return null;\n return m;\n }\n return m;\n};\n\nexport const chapterMatch = (ref: string): RegExpExecArray | null => {\n return /^([0-9]+)-?([0-9]*)$/g.exec(ref);\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\refNumPat.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\relMouseCoords.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\rememberCurrentPassage.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\removeExtension.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\removeOrbitRemote.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\resetData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\resolvePathUnderRoot.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\resolvePathUnderRoot.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\restoreScroll.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\safeFileBasename.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\safeFileBasename.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\setAudacityPref.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\sharedSegmentBoundary.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\sharedSegmentBoundary.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\sort.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\sort.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\soundtouch.js","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'no-constant-condition').","line":189,"column":7,"severity":1,"nodeType":null,"fix":{"range":[6456,6505],"text":" "}}],"suppressedMessages":[{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":121,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":121,"endColumn":18,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":127,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":127,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":133,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":133,"endColumn":8,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":148,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":148,"endColumn":9,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":153,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":153,"endColumn":10,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":161,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":161,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":225,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":225,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":228,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":228,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":231,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":231,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":234,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":234,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":237,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":237,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":240,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":240,"endColumn":8,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":244,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":244,"endColumn":6,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":247,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":247,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":265,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":265,"endColumn":12,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":272,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":272,"endColumn":10,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":279,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":279,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":285,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":285,"endColumn":10,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":290,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":290,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":301,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":301,"endColumn":27,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":304,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":304,"endColumn":9,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":320,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":320,"endColumn":11,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":323,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":323,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":340,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":340,"endColumn":21,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":347,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":347,"endColumn":18,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":350,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":350,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":353,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":353,"endColumn":18,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":363,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":363,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":377,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":377,"endColumn":10,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":399,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":399,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":402,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":402,"endColumn":8,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":428,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":428,"endColumn":8,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":432,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":432,"endColumn":18,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":448,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":448,"endColumn":16,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":505,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":505,"endColumn":21,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":508,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":508,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":518,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":518,"endColumn":25,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":533,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":533,"endColumn":14,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":540,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":540,"endColumn":20,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":573,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":573,"endColumn":26,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":589,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":589,"endColumn":32,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":622,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":622,"endColumn":37,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":667,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":667,"endColumn":29,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":678,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":678,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":698,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":698,"endColumn":10,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":705,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":705,"endColumn":16,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":732,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":732,"endColumn":10,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":792,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":792,"endColumn":12,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":815,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":815,"endColumn":9,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":833,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":833,"endColumn":8,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":837,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":837,"endColumn":11,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":847,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":847,"endColumn":12,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":868,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":868,"endColumn":18,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":871,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":871,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":874,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":874,"endColumn":34,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":875,"column":35,"nodeType":"ArrowFunctionExpression","messageId":"missingReturnType","endLine":875,"endColumn":37,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":909,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":909,"endColumn":10,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/explicit-function-return-type","severity":2,"message":"Missing return type on function.","line":918,"column":3,"nodeType":"FunctionExpression","messageId":"missingReturnType","endLine":918,"endColumn":18,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"/* eslint-disable @typescript-eslint/explicit-function-return-type */\n/*\n * SoundTouch JS audio processing library\n * Copyright (c) Olli Parviainen\n * Copyright (c) Ryan Berdeen\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n */\n\n/**\n * Giving this value for the sequence length sets automatic parameter value\n * according to tempo setting (recommended)\n */\nconst USE_AUTO_SEQUENCE_LEN = 0;\n\n/**\n * Default length of a single processing sequence, in milliseconds. This determines to how\n * long sequences the original sound is chopped in the time-stretch algorithm.\n *\n * The larger this value is, the lesser sequences are used in processing. In principle\n * a bigger value sounds better when slowing down tempo, but worse when increasing tempo\n * and vice versa.\n *\n * Increasing this value reduces computational burden and vice versa.\n */\n//const DEFAULT_SEQUENCE_MS = 130\nconst DEFAULT_SEQUENCE_MS = USE_AUTO_SEQUENCE_LEN;\n\n/**\n * Giving this value for the seek window length sets automatic parameter value\n * according to tempo setting (recommended)\n */\nconst USE_AUTO_SEEKWINDOW_LEN = 0;\n\n/**\n * Seeking window default length in milliseconds for algorithm that finds the best possible\n * overlapping location. This determines from how wide window the algorithm may look for an\n * optimal joining location when mixing the sound sequences back together.\n *\n * The bigger this window setting is, the higher the possibility to find a better mixing\n * position will become, but at the same time large values may cause a \"drifting\" artifact\n * because consequent sequences will be taken at more uneven intervals.\n *\n * If there's a disturbing artifact that sounds as if a constant frequency was drifting\n * around, try reducing this setting.\n *\n * Increasing this value increases computational burden and vice versa.\n */\n//const DEFAULT_SEEKWINDOW_MS = 25;\nconst DEFAULT_SEEKWINDOW_MS = USE_AUTO_SEEKWINDOW_LEN;\n\n/**\n * Overlap length in milliseconds. When the chopped sound sequences are mixed back together,\n * to form a continuous sound stream, this parameter defines over how long period the two\n * consecutive sequences are const to overlap each other.\n *\n * This shouldn't be that critical parameter. If you reduce the DEFAULT_SEQUENCE_MS setting\n * by a large amount, you might wish to try a smaller value on this.\n *\n * Increasing this value increases computational burden and vice versa.\n */\nconst DEFAULT_OVERLAP_MS = 8;\n\n// Table for the hierarchical mixing position seeking algorithm\nconst _SCAN_OFFSETS = [\n [\n 124, 186, 248, 310, 372, 434, 496, 558, 620, 682, 744, 806, 868, 930, 992,\n 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488, 0,\n ],\n [\n -100, -75, -50, -25, 25, 50, 75, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0,\n ],\n [\n -20, -15, -10, -5, 5, 10, 15, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0, 0,\n ],\n [-4, -3, -2, -1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n];\n\n// Adjust tempo param according to tempo, so that variating processing sequence length is used\n// at varius tempo settings, between the given low...top limits\nconst AUTOSEQ_TEMPO_LOW = 0.5; // auto setting low tempo range (-50%)\nconst AUTOSEQ_TEMPO_TOP = 2.0; // auto setting top tempo range (+100%)\n\n// sequence-ms setting values at above low & top tempo\nconst AUTOSEQ_AT_MIN = 125.0;\nconst AUTOSEQ_AT_MAX = 50.0;\nconst AUTOSEQ_K =\n (AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW);\nconst AUTOSEQ_C = AUTOSEQ_AT_MIN - AUTOSEQ_K * AUTOSEQ_TEMPO_LOW;\n\n// seek-window-ms setting values at above low & top tempo\nconst AUTOSEEK_AT_MIN = 25.0;\nconst AUTOSEEK_AT_MAX = 15.0;\nconst AUTOSEEK_K =\n (AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW);\nconst AUTOSEEK_C = AUTOSEEK_AT_MIN - AUTOSEEK_K * AUTOSEQ_TEMPO_LOW;\n\nclass AbstractFifoSamplePipe {\n constructor(createBuffers) {\n if (createBuffers) {\n this.inputBuffer = new FifoSampleBuffer();\n this.outputBuffer = new FifoSampleBuffer();\n } else {\n this.inputBuffer = this.outputBuffer = null;\n }\n }\n get inputBuffer() {\n return this._inputBuffer;\n }\n set inputBuffer(inputBuffer) {\n this._inputBuffer = inputBuffer;\n }\n get outputBuffer() {\n return this._outputBuffer;\n }\n set outputBuffer(outputBuffer) {\n this._outputBuffer = outputBuffer;\n }\n clear() {\n this._inputBuffer.clear();\n this._outputBuffer.clear();\n }\n}\nclass RateTransposer extends AbstractFifoSamplePipe {\n constructor(createBuffers) {\n super(createBuffers);\n this._reset();\n this.rate = 1;\n }\n set rate(rate) {\n this._rate = rate;\n // TODO aa filter\n }\n _reset() {\n this.slopeCount = 0;\n this.prevSampleL = 0;\n this.prevSampleR = 0;\n }\n process() {\n // TODO aa filter\n const numFrames = this._inputBuffer.frameCount;\n this._outputBuffer.ensureAdditionalCapacity(numFrames / this._rate + 1);\n const numFramesOutput = this._transpose(numFrames);\n this._inputBuffer.receive();\n this._outputBuffer.put(numFramesOutput);\n }\n _transpose(numFrames) {\n if (numFrames === 0) {\n return 0; // No work.\n }\n\n const src = this._inputBuffer.vector;\n const srcOffset = this._inputBuffer.startIndex;\n\n const dest = this._outputBuffer.vector;\n const destOffset = this._outputBuffer.endIndex;\n\n var used = 0;\n var i = 0;\n\n while (this.slopeCount < 1.0) {\n dest[destOffset + 2 * i] =\n (1.0 - this.slopeCount) * this.prevSampleL +\n this.slopeCount * src[srcOffset];\n dest[destOffset + 2 * i + 1] =\n (1.0 - this.slopeCount) * this.prevSampleR +\n this.slopeCount * src[srcOffset + 1];\n i++;\n this.slopeCount += this._rate;\n }\n\n this.slopeCount -= 1.0;\n\n if (numFrames !== 1) {\n // eslint-disable-next-line no-constant-condition\n out: while (true) {\n while (this.slopeCount > 1.0) {\n this.slopeCount -= 1.0;\n used++;\n if (used >= numFrames - 1) {\n break out;\n }\n }\n\n const srcIndex = srcOffset + 2 * used;\n dest[destOffset + 2 * i] =\n (1.0 - this.slopeCount) * src[srcIndex] +\n this.slopeCount * src[srcIndex + 2];\n dest[destOffset + 2 * i + 1] =\n (1.0 - this.slopeCount) * src[srcIndex + 1] +\n this.slopeCount * src[srcIndex + 3];\n\n i++;\n this.slopeCount += this._rate;\n }\n }\n\n this.prevSampleL = src[srcOffset + 2 * numFrames - 2];\n this.prevSampleR = src[srcOffset + 2 * numFrames - 1];\n\n return i;\n }\n}\nclass FifoSampleBuffer {\n constructor() {\n this._vector = new Float32Array();\n this._position = 0;\n this._frameCount = 0;\n }\n\n get vector() {\n return this._vector;\n }\n get position() {\n return this._position;\n }\n get startIndex() {\n return this._position * 2;\n }\n get frameCount() {\n return this._frameCount;\n }\n get endIndex() {\n return (this._position + this._frameCount) * 2;\n }\n clear(frameCount) {\n this.receive(frameCount);\n this.rewind();\n }\n put(numFrames) {\n this._frameCount += numFrames;\n }\n putSamples(samples, position, numFrames) {\n position = position || 0;\n const sourceOffset = position * 2;\n if (!(numFrames >= 0)) {\n numFrames = (samples.length - sourceOffset) / 2;\n }\n const numSamples = numFrames * 2;\n\n this.ensureCapacity(numFrames + this._frameCount);\n\n const destOffset = this.endIndex;\n this._vector.set(\n samples.subarray(sourceOffset, sourceOffset + numSamples),\n destOffset\n );\n\n this._frameCount += numFrames;\n }\n putBuffer(buffer, position, numFrames) {\n position = position || 0;\n if (!(numFrames >= 0)) {\n numFrames = buffer.frameCount - position;\n }\n this.putSamples(buffer.vector, buffer.position + position, numFrames);\n }\n receive(numFrames) {\n if (!(numFrames >= 0) || numFrames > this._frameCount) {\n numFrames = this._frameCount;\n }\n this._frameCount -= numFrames;\n this._position += numFrames;\n }\n receiveSamples(output, numFrames) {\n const numSamples = numFrames * 2;\n const sourceOffset = this.startIndex;\n output.set(this._vector.subarray(sourceOffset, sourceOffset + numSamples));\n this.receive(numFrames);\n }\n extract(output, position, numFrames) {\n const sourceOffset = this.startIndex + position * 2;\n const numSamples = numFrames * 2;\n output.set(this._vector.subarray(sourceOffset, sourceOffset + numSamples));\n }\n ensureCapacity(numFrames) {\n const minLength = numFrames * 2;\n if (this._vector.length < minLength) {\n const newVector = new Float32Array(minLength);\n newVector.set(this._vector.subarray(this.startIndex, this.endIndex));\n this._vector = newVector;\n this._position = 0;\n } else {\n this.rewind();\n }\n }\n ensureAdditionalCapacity(numFrames) {\n this.ensureCapacity(this.frameCount + numFrames);\n }\n rewind() {\n if (this._position > 0) {\n this._vector.set(this._vector.subarray(this.startIndex, this.endIndex));\n this._position = 0;\n }\n }\n}\nexport class SimpleFilter {\n constructor(sourceSound, pipe) {\n this._pipe = pipe;\n this.sourceSound = sourceSound;\n this.historyBufferSize = 22050;\n this._sourcePosition = 0;\n this.outputBufferPosition = 0;\n this._position = 0;\n }\n get pipe() {\n return this._pipe;\n }\n get position() {\n return this._position;\n }\n set position(position) {\n if (position > this._position) {\n throw new RangeError(\n 'New position may not be greater than current position'\n );\n }\n const newOutputBufferPosition =\n this.outputBufferPosition - (this._position - position);\n if (newOutputBufferPosition < 0) {\n throw new RangeError('New position falls outside of history buffer');\n }\n this.outputBufferPosition = newOutputBufferPosition;\n this._position = position;\n }\n get sourcePosition() {\n return this._sourcePosition;\n }\n set sourcePosition(sourcePosition) {\n this.clear();\n this._sourcePosition = sourcePosition;\n }\n get inputBuffer() {\n return this._pipe.inputBuffer;\n }\n get outputBuffer() {\n return this._pipe.outputBuffer;\n }\n fillInputBuffer(numFrames) {\n const samples = new Float32Array(numFrames * 2);\n const numFramesExtracted = this.sourceSound.extract(\n samples,\n numFrames,\n this._sourcePosition\n );\n this._sourcePosition += numFramesExtracted;\n this.inputBuffer.putSamples(samples, 0, numFramesExtracted);\n }\n fillOutputBuffer(numFrames) {\n while (this.outputBuffer.frameCount < numFrames) {\n // TODO hardcoded buffer size\n const numInputFrames = 8192 * 2 - this.inputBuffer.frameCount;\n\n this.fillInputBuffer(numInputFrames);\n\n if (this.inputBuffer.frameCount < 8192 * 2) {\n break;\n // TODO flush pipe\n }\n this._pipe.process();\n }\n }\n extract(target, numFrames) {\n this.fillOutputBuffer(this.outputBufferPosition + numFrames);\n\n const numFramesExtracted = Math.min(\n numFrames,\n this.outputBuffer.frameCount - this.outputBufferPosition\n );\n this.outputBuffer.extract(\n target,\n this.outputBufferPosition,\n numFramesExtracted\n );\n\n const currentFrames = this.outputBufferPosition + numFramesExtracted;\n this.outputBufferPosition = Math.min(this.historyBufferSize, currentFrames);\n this.outputBuffer.receive(\n Math.max(currentFrames - this.historyBufferSize, 0)\n );\n\n this._position += numFramesExtracted;\n return numFramesExtracted;\n }\n handleSampleData(e) {\n this.extract(e.data, 4096);\n }\n clear() {\n // TODO yuck\n this._pipe.clear();\n this.outputBufferPosition = 0;\n }\n}\nclass Stretch extends AbstractFifoSamplePipe {\n constructor(createBuffers, sampleRate) {\n super(createBuffers);\n this.bQuickSeek = true;\n this.bMidBufferDirty = false;\n\n this.pMidBuffer = null;\n this.overlapLength = 0;\n\n this.bAutoSeqSetting = true;\n this.bAutoSeekSetting = true;\n\n this._tempo = 1;\n this.setParameters(\n sampleRate,\n DEFAULT_SEQUENCE_MS,\n DEFAULT_SEEKWINDOW_MS,\n DEFAULT_OVERLAP_MS\n );\n }\n clear() {\n AbstractFifoSamplePipe.prototype.clear.call(this);\n this._clearMidBuffer();\n }\n _clearMidBuffer() {\n if (this.bMidBufferDirty) {\n this.bMidBufferDirty = false;\n this.pMidBuffer = null;\n }\n }\n /**\n * Sets routine control parameters. These control are certain time constants\n * defining how the sound is stretched to the desired duration.\n *\n * 'sampleRate' = sample rate of the sound\n * 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms)\n * 'seekwindowMS' = seeking window length for scanning the best overlapping\n * position (default = 28 ms)\n * 'overlapMS' = overlapping length (default = 12 ms)\n */\n setParameters(aSampleRate, aSequenceMS, aSeekWindowMS, aOverlapMS) {\n // accept only positive parameter values - if zero or negative, use old values instead\n if (aSampleRate > 0) {\n this.sampleRate = aSampleRate;\n }\n if (aOverlapMS > 0) {\n this.overlapMs = aOverlapMS;\n }\n\n if (aSequenceMS > 0) {\n this.sequenceMs = aSequenceMS;\n this.bAutoSeqSetting = false;\n } else {\n // zero or below, use automatic setting\n this.bAutoSeqSetting = true;\n }\n\n if (aSeekWindowMS > 0) {\n this.seekWindowMs = aSeekWindowMS;\n this.bAutoSeekSetting = false;\n } else {\n // zero or below, use automatic setting\n this.bAutoSeekSetting = true;\n }\n\n this.calcSeqParameters();\n\n this.calculateOverlapLength(this.overlapMs);\n\n // set tempo to recalculate 'sampleReq'\n this.tempo = this._tempo;\n }\n\n /**\n * Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower\n * tempo, larger faster tempo.\n */\n set tempo(newTempo) {\n var intskip;\n\n this._tempo = newTempo;\n\n // Calculate new sequence duration\n this.calcSeqParameters();\n\n // Calculate ideal skip length (according to tempo value)\n this.nominalSkip =\n this._tempo * (this.seekWindowLength - this.overlapLength);\n this.skipFract = 0;\n intskip = Math.floor(this.nominalSkip + 0.5);\n\n // Calculate how many samples are needed in the 'inputBuffer' to\n // process another batch of samples\n this.sampleReq =\n Math.max(intskip + this.overlapLength, this.seekWindowLength) +\n this.seekLength;\n }\n get inputChunkSize() {\n return this.sampleReq;\n }\n get outputChunkSize() {\n return (\n this.overlapLength +\n Math.max(0, this.seekWindowLength - 2 * this.overlapLength)\n );\n }\n\n /**\n * Calculates overlapInMsec period length in samples.\n */\n calculateOverlapLength(overlapInMsec) {\n // TODO assert(overlapInMsec >= 0);\n var newOvl = (this.sampleRate * overlapInMsec) / 1000;\n if (newOvl < 16) {\n newOvl = 16;\n }\n\n // must be divisible by 8\n newOvl -= newOvl % 8;\n\n this.overlapLength = newOvl;\n\n this.pRefMidBuffer = new Float32Array(this.overlapLength * 2);\n this.pMidBuffer = new Float32Array(this.overlapLength * 2);\n }\n checkLimits(x, mi, ma) {\n return x < mi ? mi : x > ma ? ma : x;\n }\n\n /**\n * Calculates processing sequence length according to tempo setting\n */\n calcSeqParameters() {\n var seq;\n var seek;\n\n if (this.bAutoSeqSetting) {\n seq = AUTOSEQ_C + AUTOSEQ_K * this._tempo;\n seq = this.checkLimits(seq, AUTOSEQ_AT_MAX, AUTOSEQ_AT_MIN);\n this.sequenceMs = Math.floor(seq + 0.5);\n }\n\n if (this.bAutoSeekSetting) {\n seek = AUTOSEEK_C + AUTOSEEK_K * this._tempo;\n seek = this.checkLimits(seek, AUTOSEEK_AT_MAX, AUTOSEEK_AT_MIN);\n this.seekWindowMs = Math.floor(seek + 0.5);\n }\n\n // Update seek window lengths\n this.seekWindowLength = Math.floor(\n (this.sampleRate * this.sequenceMs) / 1000\n );\n this.seekLength = Math.floor((this.sampleRate * this.seekWindowMs) / 1000);\n }\n\n /**\n * Enables/disables the quick position seeking algorithm.\n */\n set quickSeek(enable) {\n this.bQuickSeek = enable;\n }\n\n /**\n * Seeks for the optimal overlap-mixing position.\n */\n seekBestOverlapPosition() {\n if (this.bQuickSeek) {\n return this.seekBestOverlapPositionStereoQuick();\n } else {\n return this.seekBestOverlapPositionStereo();\n }\n }\n\n /**\n * Seeks for the optimal overlap-mixing position. The 'stereo' version of the\n * routine\n *\n * The best position is determined as the position where the two overlapped\n * sample sequences are 'most alike', in terms of the highest cross-correlation\n * value over the overlapping period\n */\n seekBestOverlapPositionStereo() {\n var bestOffs, bestCorr, corr, i;\n\n // Slopes the amplitudes of the 'midBuffer' samples.\n this.precalcCorrReferenceStereo();\n\n bestCorr = Number.MIN_VALUE;\n bestOffs = 0;\n\n // Scans for the best correlation value by testing each possible position\n // over the permitted range.\n for (i = 0; i < this.seekLength; i++) {\n // Calculates correlation value for the mixing position corresponding\n // to 'i'\n corr = this.calcCrossCorrStereo(2 * i, this.pRefMidBuffer);\n\n // Checks for the highest correlation value.\n if (corr > bestCorr) {\n bestCorr = corr;\n bestOffs = i;\n }\n }\n return bestOffs;\n }\n\n /**\n * Seeks for the optimal overlap-mixing position. The 'stereo' version of the\n * routine\n *\n * The best position is determined as the position where the two overlapped\n * sample sequences are 'most alike', in terms of the highest cross-correlation\n * value over the overlapping period\n */\n seekBestOverlapPositionStereoQuick() {\n var j, bestOffs, bestCorr, corr, scanCount, corrOffset, tempOffset;\n\n // Slopes the amplitude of the 'midBuffer' samples\n this.precalcCorrReferenceStereo();\n\n bestCorr = Number.MIN_VALUE;\n bestOffs = 0;\n corrOffset = 0;\n tempOffset = 0;\n\n // Scans for the best correlation value using four-pass hierarchical search.\n //\n // The look-up table 'scans' has hierarchical position adjusting steps.\n // In first pass the routine searhes for the highest correlation with\n // relatively coarse steps, then rescans the neighbourhood of the highest\n // correlation with better resolution and so on.\n for (scanCount = 0; scanCount < 4; scanCount++) {\n j = 0;\n while (_SCAN_OFFSETS[scanCount][j]) {\n tempOffset = corrOffset + _SCAN_OFFSETS[scanCount][j];\n if (tempOffset >= this.seekLength) {\n break;\n }\n\n // Calculates correlation value for the mixing position corresponding\n // to 'tempOffset'\n corr = this.calcCrossCorrStereo(2 * tempOffset, this.pRefMidBuffer);\n\n // Checks for the highest correlation value\n if (corr > bestCorr) {\n bestCorr = corr;\n bestOffs = tempOffset;\n }\n j++;\n }\n corrOffset = bestOffs;\n }\n return bestOffs;\n }\n\n /**\n * Slopes the amplitude of the 'midBuffer' samples so that cross correlation\n * is faster to calculate\n */\n precalcCorrReferenceStereo() {\n var i, cnt2, temp;\n\n for (i = 0; i < this.overlapLength; i++) {\n temp = i * (this.overlapLength - i);\n cnt2 = i * 2;\n this.pRefMidBuffer[cnt2] = this.pMidBuffer[cnt2] * temp;\n this.pRefMidBuffer[cnt2 + 1] = this.pMidBuffer[cnt2 + 1] * temp;\n }\n }\n\n calcCrossCorrStereo(mixingPos, compare) {\n const mixing = this._inputBuffer.vector;\n mixingPos += this._inputBuffer.startIndex;\n\n var corr, i, mixingOffset;\n corr = 0;\n for (i = 2; i < 2 * this.overlapLength; i += 2) {\n mixingOffset = i + mixingPos;\n corr +=\n mixing[mixingOffset] * compare[i] +\n mixing[mixingOffset + 1] * compare[i + 1];\n }\n return corr;\n }\n\n // TODO inline\n /**\n * Overlaps samples in 'midBuffer' with the samples in 'pInputBuffer' at position\n * of 'ovlPos'.\n */\n overlap(ovlPos) {\n this.overlapStereo(2 * ovlPos);\n }\n\n /**\n * Overlaps samples in 'midBuffer' with the samples in 'pInput'\n */\n overlapStereo(pInputPos) {\n const pInput = this._inputBuffer.vector;\n pInputPos += this._inputBuffer.startIndex;\n\n var pOutput = this._outputBuffer.vector,\n pOutputPos = this._outputBuffer.endIndex,\n i,\n cnt2,\n fTemp,\n fScale,\n fi,\n pInputOffset,\n pOutputOffset;\n\n fScale = 1 / this.overlapLength;\n for (i = 0; i < this.overlapLength; i++) {\n fTemp = (this.overlapLength - i) * fScale;\n fi = i * fScale;\n cnt2 = 2 * i;\n pInputOffset = cnt2 + pInputPos;\n pOutputOffset = cnt2 + pOutputPos;\n pOutput[pOutputOffset + 0] =\n pInput[pInputOffset + 0] * fi + this.pMidBuffer[cnt2 + 0] * fTemp;\n pOutput[pOutputOffset + 1] =\n pInput[pInputOffset + 1] * fi + this.pMidBuffer[cnt2 + 1] * fTemp;\n }\n }\n process() {\n var ovlSkip, offset, temp;\n if (this.pMidBuffer === null) {\n // if midBuffer is empty, move the first samples of the input stream\n // into it\n if (this._inputBuffer.frameCount < this.overlapLength) {\n // wait until we've got overlapLength samples\n return;\n }\n this.pMidBuffer = new Float32Array(this.overlapLength * 2);\n this._inputBuffer.receiveSamples(this.pMidBuffer, this.overlapLength);\n }\n\n // Process samples as long as there are enough samples in 'inputBuffer'\n // to form a processing frame.\n while (this._inputBuffer.frameCount >= this.sampleReq) {\n // If tempo differs from the normal ('SCALE'), scan for the best overlapping\n // position\n offset = this.seekBestOverlapPosition();\n\n // Mix the samples in the 'inputBuffer' at position of 'offset' with the\n // samples in 'midBuffer' using sliding overlapping\n // ... first partially overlap with the end of the previous sequence\n // (that's in 'midBuffer')\n this._outputBuffer.ensureAdditionalCapacity(this.overlapLength);\n // FIXME unit?\n //overlap(uint(offset));\n this.overlap(Math.floor(offset));\n this._outputBuffer.put(this.overlapLength);\n\n // ... then copy sequence samples from 'inputBuffer' to output\n temp = this.seekWindowLength - 2 * this.overlapLength; // & 0xfffffffe;\n if (temp > 0) {\n this._outputBuffer.putBuffer(\n this._inputBuffer,\n offset + this.overlapLength,\n temp\n );\n }\n\n // Copies the end of the current sequence from 'inputBuffer' to\n // 'midBuffer' for being mixed with the beginning of the next\n // processing sequence and so on\n //assert(offset + seekWindowLength <= (int)inputBuffer.numSamples());\n const start =\n this.inputBuffer.startIndex +\n 2 * (offset + this.seekWindowLength - this.overlapLength);\n this.pMidBuffer.set(\n this._inputBuffer.vector.subarray(start, start + 2 * this.overlapLength)\n );\n\n // Remove the processed samples from the input buffer. Update\n // the difference between integer & nominal skip step to 'skipFract'\n // in order to prevent the error from accumulating over time.\n this.skipFract += this.nominalSkip; // real skip size\n ovlSkip = Math.floor(this.skipFract); // rounded to integer skip\n this.skipFract -= ovlSkip; // maintain the fraction part, i.e. real vs. integer skip\n this._inputBuffer.receive(ovlSkip);\n }\n }\n get tempo() {\n return this._tempo;\n }\n}\nexport class SoundTouch {\n constructor(sampleRate) {\n this.rateTransposer = new RateTransposer(false);\n this.tdStretch = new Stretch(false, sampleRate);\n\n this._inputBuffer = new FifoSampleBuffer();\n this._intermediateBuffer = new FifoSampleBuffer();\n this._outputBuffer = new FifoSampleBuffer();\n\n this._rate = 0;\n this._tempo = 0;\n\n this.virtualPitch = 1.0;\n this.virtualRate = 1.0;\n this.virtualTempo = 1.0;\n\n this._calculateEffectiveRateAndTempo();\n }\n\n extend(a, b) {\n for (const i in b) {\n const g = b.__lookupGetter__(i),\n s = b.__lookupSetter__(i);\n if (g || s) {\n if (g) {\n a.__defineGetter__(i, g);\n }\n if (s) {\n a.__defineSetter__(i, s);\n }\n } else {\n a[i] = b[i];\n }\n }\n return a;\n }\n\n clear() {\n this.rateTransposer.clear();\n this.tdStretch.clear();\n }\n get rate() {\n return this._rate;\n }\n set rate(rate) {\n this.virtualRate = rate;\n this._calculateEffectiveRateAndTempo();\n }\n set rateChange(rateChange) {\n this.rate = 1.0 + 0.01 * rateChange;\n }\n get tempo() {\n return this._tempo;\n }\n set tempo(tempo) {\n this.virtualTempo = tempo;\n this._calculateEffectiveRateAndTempo();\n }\n set tempoChange(tempoChange) {\n this.tempo = 1.0 + 0.01 * tempoChange;\n }\n set pitch(pitch) {\n this.virtualPitch = pitch;\n this._calculateEffectiveRateAndTempo();\n }\n set pitchOctaves(pitchOctaves) {\n this.pitch = Math.exp(0.69314718056 * pitchOctaves);\n this._calculateEffectiveRateAndTempo();\n }\n set pitchSemitones(pitchSemitones) {\n this.pitchOctaves = pitchSemitones / 12.0;\n }\n get inputBuffer() {\n return this._inputBuffer;\n }\n get outputBuffer() {\n return this._outputBuffer;\n }\n _calculateEffectiveRateAndTempo() {\n const testFloatEqual = (a, b) => {\n return (a > b ? a - b : b - a) > 1e-10;\n };\n const previousTempo = this._tempo;\n const previousRate = this._rate;\n\n this._tempo = this.virtualTempo / this.virtualPitch;\n this._rate = this.virtualRate * this.virtualPitch;\n\n if (testFloatEqual(this._tempo, previousTempo)) {\n this.tdStretch.tempo = this._tempo;\n }\n if (testFloatEqual(this._rate, previousRate)) {\n this.rateTransposer.rate = this._rate;\n }\n\n if (this._rate > 1.0) {\n if (this._outputBuffer !== this.rateTransposer.outputBuffer) {\n this.tdStretch.inputBuffer = this._inputBuffer;\n this.tdStretch.outputBuffer = this._intermediateBuffer;\n\n this.rateTransposer.inputBuffer = this._intermediateBuffer;\n this.rateTransposer.outputBuffer = this._outputBuffer;\n }\n } else {\n if (this._outputBuffer !== this.tdStretch.outputBuffer) {\n this.rateTransposer.inputBuffer = this._inputBuffer;\n this.rateTransposer.outputBuffer = this._intermediateBuffer;\n\n this.tdStretch.inputBuffer = this._intermediateBuffer;\n this.tdStretch.outputBuffer = this._outputBuffer;\n }\n }\n }\n process() {\n if (this._rate > 1.0) {\n this.tdStretch.process();\n this.rateTransposer.process();\n } else {\n this.rateTransposer.process();\n this.tdStretch.process();\n }\n }\n getWebAudioNode(context, filter) {\n const BUFFER_SIZE = 4096;\n const node = context.createScriptProcessor(BUFFER_SIZE, 2, 2),\n samples = new Float32Array(BUFFER_SIZE * 2);\n node.onaudioprocess = function (e) {\n const l = e.outputBuffer.getChannelData(0),\n r = e.outputBuffer.getChannelData(1);\n const framesExtracted = filter.extract(samples, BUFFER_SIZE);\n if (framesExtracted === 0) {\n node.disconnect(); // Pause.\n }\n for (var i = 0; i < framesExtracted; i++) {\n l[i] = samples[i * 2];\n r[i] = samples[i * 2 + 1];\n }\n };\n return node;\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\startEnd.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\storedCompareKey.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\stringAvatar.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'no-bitwise').","line":7,"column":3,"severity":1,"nodeType":null,"fix":{"range":[132,163],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { AvatarProps, SxProps } from '@mui/material';\n\nfunction stringToColor(string: string): string {\n let hash = 0;\n let i;\n\n /* eslint-disable no-bitwise */\n for (i = 0; i < string.length; i += 1) {\n hash = string.charCodeAt(i) + ((hash << 5) - hash);\n }\n\n let color = '#';\n\n for (i = 0; i < 3; i += 1) {\n const value = (hash >> (i * 8)) & 0xff;\n color += `00${value.toString(16)}`.slice(-2);\n }\n /* eslint-enable no-bitwise */\n\n return color;\n}\n\nconst initials = (name: string): string => {\n const [firstName, lastName] = name.split(' ');\n if (firstName && lastName) return `${firstName[0]}${lastName[0]}`;\n if (firstName) return `${firstName[0]}`;\n return '';\n};\n\nexport function stringAvatar(name: string, sxProps?: SxProps): AvatarProps {\n return {\n sx: { ...sxProps, bgcolor: stringToColor(name) },\n children: `${initials(name)}`,\n };\n}\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\syncRemoteAuthHeaders.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\timeFmt.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\toCamel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\transcriptionEaf.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\translateParatextError.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\tryDownload.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":31,"column":12,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":31,"endColumn":36,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\tryDownload.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\tryParseJson.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\typeLimit.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\uiLang.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\updateXml.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\urlToFile.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useAudioAi.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useBookN.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useCanPublish.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'accessToken', 'canUserPublish', 'errorReporter', 'getCanPublish', 'isOffline', 'memory', 'paratext_canPublish', 'resetCanPublish', 't.checkingParatext', 'user', and 'users'. Either include them or remove the dependency array.","line":96,"column":6,"nodeType":"ArrayExpression","endLine":96,"endColumn":33,"suggestions":[{"desc":"Update the dependencies array to be: [accessToken, canUserPublish, errorReporter, getCanPublish, isOffline, memory, paratext_canPublish, paratext_canPublishStatus, resetCanPublish, t.checkingParatext, user, users]","fix":{"range":[3735,3762],"text":"[accessToken, canUserPublish, errorReporter, getCanPublish, isOffline, memory, paratext_canPublish, paratext_canPublishStatus, resetCanPublish, t.checkingParatext, user, users]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useCheckOnline.test.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":84,"column":7,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":84,"endColumn":34,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-require-imports","severity":2,"message":"A `require()` style import is forbidden.","line":109,"column":7,"nodeType":"CallExpression","messageId":"noRequireImports","endLine":109,"endColumn":34,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useCheckOnline.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from '@typescript-eslint/explicit-function-return-type').","line":30,"column":1,"severity":1,"nodeType":null,"fix":{"range":[898,948],"text":""}}],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'label' is defined but never used. Allowed unused args must match /^_/u.","line":31,"column":32,"nodeType":null,"messageId":"unusedVar","endLine":31,"endColumn":37,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"import { useGetGlobal, useGlobal } from '../context/useGlobal';\nimport * as actions from '../store';\nimport Axios from 'axios';\nimport JSONAPISource from '@orbit/jsonapi';\nimport { API_CONFIG, OrbitNetworkErrorRetries } from '../../api-variable';\nimport { useDispatch } from 'react-redux';\nimport { LocalKey } from '../utils';\nimport Bugsnag from '@bugsnag/js';\nimport { orbitReset } from '../crud/orbitReset';\n\nexport function Online(doCheck: boolean, cb: (result: boolean) => void): void {\n const opts = {\n timeout: 10000,\n };\n\n //if we're electron, don't be using the internet even if it's available\n //until the user logs in or the override is true\n if (!doCheck) {\n cb(false);\n }\n\n Axios.get(API_CONFIG.host + '/api/AmIOnline/', opts)\n .then(() => {\n cb(true);\n })\n .catch((reason) => {\n cb(reason.response !== undefined);\n });\n}\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/no-unused-vars\nexport const useCheckOnline = (label: string) => {\n const dispatch = useDispatch();\n const resetOrbitError = actions.resetOrbitError;\n const getGlobal = useGetGlobal();\n const [, setConnected] = useGlobal('connected');\n const [, setOrbitRetries] = useGlobal('orbitRetries');\n const [coordinator] = useGlobal('coordinator');\n const remote = coordinator?.getSource('remote') as JSONAPISource;\n\n const errorReset = async () => {\n dispatch(resetOrbitError());\n await orbitReset(remote, setOrbitRetries);\n // queue.retry() can re-dispatch ORBIT_RETRY via Sources updateError; clear\n // again so a later Record remount does not re-snack (TT-7720).\n dispatch(resetOrbitError());\n };\n\n const checkOnline = (\n cb: (result: boolean) => void,\n forceCheck: boolean = false\n ): void => {\n if (!forceCheck && getGlobal('offline')) {\n localStorage.setItem(LocalKey.connected, 'false');\n }\n const statusChange = (result: boolean) => {\n localStorage.setItem(\n LocalKey.connected,\n `${result && !getGlobal('offline')}`\n );\n if (API_CONFIG.snagId !== '') {\n if (result) {\n Bugsnag.resumeSession();\n } else {\n Bugsnag.pauseSession();\n }\n }\n setConnected(result);\n };\n //console.log('Checking online status for ' + label);\n Online(forceCheck || !getGlobal('offline'), (result) => {\n // TT-7720: clear stale orbit network-error snack when AmIOnline succeeds\n // even if `connected` is already true (Pending Retry / CloudOff paths).\n // Only run full orbitReset (queue.retry) on a false→true edge — retrying\n // the queue while already online re-fires non-network failures (e.g. 403\n // on passagestatechanges) and can surface a spurious API Error 500 page.\n if (result) {\n if (getGlobal('connected') !== result) {\n errorReset().finally(() => {\n statusChange(result);\n });\n } else {\n dispatch(resetOrbitError());\n setOrbitRetries(OrbitNetworkErrorRetries);\n }\n } else if (getGlobal('connected') !== result) {\n statusChange(result);\n }\n cb(result);\n });\n };\n return checkOnline;\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useCompression.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useDataChanges.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useDebounce.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useHasParatext.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'isOffline'. Either include it or remove the dependency array.","line":40,"column":6,"nodeType":"ArrayExpression","endLine":40,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [isOffline]","fix":{"range":[1793,1795],"text":"[isOffline]"}}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has missing dependencies: 'getUserName', 'ptPath', and 't.checkingParatext'. Either include them or remove the dependency array. You can also replace multiple useState variables with useReducer if 'setHasParatext' needs the current value of 'ptPath'.","line":56,"column":6,"nodeType":"ArrayExpression","endLine":62,"endColumn":4,"suggestions":[{"desc":"Update the dependencies array to be: [accessToken, errorReporter, getUserName, isOffline, paratext_username, paratext_usernameStatus, ptPath, t.checkingParatext]","fix":{"range":[2178,2286],"text":"[accessToken, errorReporter, getUserName, isOffline, paratext_username, paratext_usernameStatus, ptPath, t.checkingParatext]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useHome.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useInterval.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useIsPapLike.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useJsonParams.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useLocLangName.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useLogoutResets.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useMobile.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useMobile.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useMounted.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":1,"message":"'title' is defined but never used. Allowed unused args must match /^_/u.","line":5,"column":28,"nodeType":null,"messageId":"unusedVar","endLine":5,"endColumn":33,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useLayoutEffect has a missing dependency: 'isDev'. Either include it or remove the dependency array.","line":21,"column":6,"nodeType":"ArrayExpression","endLine":21,"endColumn":8,"suggestions":[{"desc":"Update the dependencies array to be: [isDev]","fix":{"range":[660,662],"text":"[isDev]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useMyNavigate.test.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useMyNavigate.ts","messages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'navigate'. Either include it or remove the dependency array.","line":22,"column":6,"nodeType":"ArrayExpression","endLine":22,"endColumn":12,"suggestions":[{"desc":"Update the dependencies array to be: [goTo, navigate]","fix":{"range":[679,685],"text":"[goTo, navigate]"}}]}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NavigateOptions, To, useNavigate } from 'react-router-dom';\nimport { useHome } from './useHome';\nimport { useEffect, useState } from 'react';\n\nconst cancelListeners = new Set<() => void>();\n\n/* A navigation issued through useMyNavigate was blocked and the user chose to stay. */\nexport const navigationCancelled = (): void => {\n cancelListeners.forEach((cb) => cb());\n};\n\nexport const useMyNavigate = (): typeof myNavigate => {\n const navigate = useNavigate();\n const { checkHome } = useHome();\n const [goTo, setGoTo] = useState<{\n to: To;\n options: NavigateOptions | undefined;\n }>();\n\n useEffect(() => {\n if (goTo) navigate(goTo.to, goTo.options);\n }, [goTo]);\n\n useEffect(() => {\n const clear = () => setGoTo(undefined);\n cancelListeners.add(clear);\n return () => {\n cancelListeners.delete(clear);\n };\n }, []);\n\n function myNavigate(to: To, options?: NavigateOptions): void {\n checkHome(to);\n if (to !== goTo?.to) setGoTo({ to, options });\n }\n return myNavigate;\n};\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useNewTime.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useNum2BookCode.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useProjectPermissions.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'userIsOrgAdmin'. Either include it or remove the dependency array.","line":35,"column":6,"nodeType":"ArrayExpression","endLine":35,"endColumn":25,"suggestions":[{"desc":"Update the dependencies array to be: [team, userIsAdmin, userIsOrgAdmin]","fix":{"range":[1400,1419],"text":"[team, userIsAdmin, userIsOrgAdmin]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useProjectsLoaded.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useRenderingTrace.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'no-console').","line":39,"column":7,"severity":1,"nodeType":null,"fix":{"range":[1346,1384],"text":" "}},{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'no-console').","line":42,"column":7,"severity":1,"nodeType":null,"fix":{"range":[1477,1515],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":2,"source":"import { useEffect, useRef } from 'react';\n\n/**\n * Helps tracking the props changes made in a react functional component.\n *\n * Prints the name of the properties/states variables causing a render (or re-render).\n * For debugging purposes only.\n *\n * @usage You can simply track the props of the components like this:\n * useRenderingTrace('MyComponent', props);\n *\n * @usage You can also track additional state like this:\n * const [someState] = useState(null);\n * useRenderingTrace('MyComponent', { ...props, someState });\n *\n * @param componentName Name of the component to display\n * @param propsAndStates\n * @param level\n *\n * @see https://stackoverflow.com/a/51082563/2391795\n */\nfunction useRenderingTrace<\n T extends Record,\n L extends 'debug' | 'info' | 'log' = 'debug',\n>(componentName: string, propsAndStates: T, level: L = 'debug' as L): void {\n const prev = useRef(propsAndStates);\n\n useEffect(() => {\n type Diff = { [K in keyof T]?: { old: T[K] | undefined; new: T[K] } };\n const changedProps = (\n Object.entries(propsAndStates) as Array<[keyof T, T[keyof T]]>\n ).reduce((acc, [key, value]) => {\n if (prev.current[key] !== value) {\n acc[key] = { old: prev.current[key], new: value };\n }\n return acc;\n }, {});\n if (Object.keys(changedProps).length > 0) {\n // eslint-disable-next-line no-console\n console[level](`[${componentName}] Changed props:`, changedProps);\n } else {\n // eslint-disable-next-line no-console\n console[level](`[${componentName}] no changed props:`);\n }\n\n prev.current = propsAndStates;\n });\n}\n\nexport default useRenderingTrace;\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useStepPermission.test.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useStepPermission.ts","messages":[],"suppressedMessages":[{"ruleId":"react-hooks/exhaustive-deps","severity":1,"message":"React Hook useEffect has a missing dependency: 'getOrgDefault'. Either include it or remove the dependency array.","line":39,"column":6,"nodeType":"ArrayExpression","endLine":39,"endColumn":21,"suggestions":[{"desc":"Update the dependencies array to be: [getOrgDefault, organizations]","fix":{"range":[1727,1742],"text":"[getOrgDefault, organizations]"}}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useTraceUpdate.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'no-console').","line":22,"column":7,"severity":1,"nodeType":null,"fix":{"range":[614,652],"text":" "}},{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'no-console').","line":25,"column":9,"severity":1,"nodeType":null,"fix":{"range":[769,807],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":2,"source":"import { useEffect, useRef } from 'react';\n\n// To print out what props are changing\n// usage: useTraceUpdate(props) inside your component\nexport function useTraceUpdate>(\n props: T\n): void {\n const prev = useRef(props);\n\n useEffect(() => {\n const changedProps: Partial<\n Record\n > = {};\n\n (Object.keys(props) as Array).forEach((k) => {\n if (prev.current[k] !== props[k]) {\n changedProps[k] = [prev.current[k], props[k]];\n }\n });\n\n if (Object.keys(changedProps).length > 0) {\n // eslint-disable-next-line no-console\n console.log('Changed props:');\n (Object.keys(changedProps) as Array).forEach((key) => {\n // eslint-disable-next-line no-console\n console.log(String(key), changedProps[key]);\n });\n }\n prev.current = props;\n });\n}\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useWaitForRemoteQueue.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\useWfLabel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\validateEmail.ts","messages":[{"ruleId":null,"message":"Unused eslint-disable directive (no problems were reported from 'no-useless-escape').","line":2,"column":3,"severity":1,"nodeType":null,"fix":{"range":[58,106],"text":" "}}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":1,"source":"export function validateEmail(email: string): boolean {\n /* eslint-disable-next-line no-useless-escape */\n const re =\n /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n return re.test(email.toLowerCase());\n}\nexport function validateMultipleEmails(emails: string): boolean {\n const emailList = emails.split(';');\n for (const email of emailList) {\n if (!validateEmail(email.trim())) {\n return false;\n }\n }\n return true;\n}\n","usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\waitForIt.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\src\\utils\\wav.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"C:\\Users\\gtrih\\git\\apm-vite\\web\\vite.config.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]}] \ No newline at end of file From 2a9c1d0629e07a3e220bbaaeaa7779f6e162400f Mon Sep 17 00:00:00 2001 From: Greg Trihus Date: Fri, 9 Oct 2026 07:56:21 -0500 Subject: [PATCH 2/2] no report in repo --- web/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/web/.gitignore b/web/.gitignore index 6c8c64b0d..bd8bdf4e9 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -52,3 +52,4 @@ dist/ node_modules/ aws-exports.js awsconfiguration.json +eslint-report.json