From 6608dd392f101397d7b7a865b64267819f0e80eb Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 7 Apr 2026 07:46:49 +0000 Subject: [PATCH] fix(client): correct prettier endOfLine and oxlint disable directives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Client Typecheck & Test CI job was failing on the prettier format check. Two real root causes, fixed properly: 1. prettier endOfLine was set to 'crlf' but the repo stores files with LF (no .gitattributes forcing eol), so 'prettier --check' failed on 292 files on the Linux CI runner. Set endOfLine to 'lf' to match the on-disk reality. Also reformat the 2 files (pluginBridge.ts, solidAdapter.ts) that had genuine style issues. 2. 15 'eslint-disable-next-line' comments targeted oxlint-only rules (no-await-in-loop, no-unassigned-vars) that ESLint does not enable, so ESLint reported them as 'Unused eslint-disable directive' warnings. Switched the directive prefix to 'oxlint-disable-next-line' — oxlint still honors them (its native syntax), and ESLint no longer parses them as eslint directives, so the warnings are gone without suppressing the safety check or removing the directives that oxlint actually relies on. Verified locally: oxlint, tsc --noEmit, eslint, prettier --check, and npm audit --audit-level=high all exit 0. --- Client/tauri-client/package.json | 2 +- .../src/components/settings/AdvancedTab.ts | 2 +- .../src/components/solid/PluginContainer.tsx | 2 +- Client/tauri-client/src/lib/livekitSession.ts | 20 +++++++++---------- Client/tauri-client/src/lib/logPersistence.ts | 4 ++-- Client/tauri-client/src/lib/pluginBridge.ts | 6 +++++- Client/tauri-client/src/lib/screenShare.ts | 2 +- Client/tauri-client/src/lib/solidAdapter.ts | 6 +----- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Client/tauri-client/package.json b/Client/tauri-client/package.json index 7b8e2f1c..ff36eb12 100644 --- a/Client/tauri-client/package.json +++ b/Client/tauri-client/package.json @@ -57,7 +57,7 @@ "printWidth": 100, "tabWidth": 2, "arrowParens": "always", - "endOfLine": "crlf" + "endOfLine": "lf" }, "dependencies": { "@jitsi/rnnoise-wasm": "^0.2.1", diff --git a/Client/tauri-client/src/components/settings/AdvancedTab.ts b/Client/tauri-client/src/components/settings/AdvancedTab.ts index 3cb0d496..b0383977 100644 --- a/Client/tauri-client/src/components/settings/AdvancedTab.ts +++ b/Client/tauri-client/src/components/settings/AdvancedTab.ts @@ -311,7 +311,7 @@ async function clearLogFiles(): Promise { const entries = await readDir(logDir); for (const entry of entries) { if (entry.name?.endsWith(".jsonl") && !entry.isDirectory) { - // eslint-disable-next-line no-await-in-loop -- sequential file deletion to avoid overwhelming the filesystem + // oxlint-disable-next-line no-await-in-loop -- sequential file deletion to avoid overwhelming the filesystem await remove(`${logDir}/${entry.name}`); } } diff --git a/Client/tauri-client/src/components/solid/PluginContainer.tsx b/Client/tauri-client/src/components/solid/PluginContainer.tsx index ad3284a6..afe1c640 100644 --- a/Client/tauri-client/src/components/solid/PluginContainer.tsx +++ b/Client/tauri-client/src/components/solid/PluginContainer.tsx @@ -14,7 +14,7 @@ export interface PluginContainerProps { } export function PluginContainer(props: PluginContainerProps): JSX.Element { - // eslint-disable-next-line no-unassigned-vars -- Solid ref assigned by JSX ref={host} + // oxlint-disable-next-line no-unassigned-vars -- Solid ref assigned by JSX ref={host} let host!: HTMLDivElement; let dispose: (() => void) | undefined; diff --git a/Client/tauri-client/src/lib/livekitSession.ts b/Client/tauri-client/src/lib/livekitSession.ts index 72aa6c17..f8ab99d5 100644 --- a/Client/tauri-client/src/lib/livekitSession.ts +++ b/Client/tauri-client/src/lib/livekitSession.ts @@ -398,7 +398,7 @@ export class LiveKitSession { attempt, maxAttempts: LiveKitSession.MAX_RECONNECT_ATTEMPTS, }); - // eslint-disable-next-line no-await-in-loop -- intentional sequential polling with backoff delay + // oxlint-disable-next-line no-await-in-loop -- intentional sequential polling with backoff delay await new Promise((r) => setTimeout(r, LiveKitSession.RECONNECT_DELAY_MS)); // If user manually left or joined a different channel during the delay, abort. if (signal.aborted || this._currentChannelId !== channelId) { @@ -435,7 +435,7 @@ export class LiveKitSession { return; } - // eslint-disable-next-line no-await-in-loop -- sequential reconnect: resolve URL then connect + // oxlint-disable-next-line no-await-in-loop -- sequential reconnect: resolve URL then connect const resolvedUrl = await this.resolveLiveKitUrl(url, directUrl); if (signal.aborted || this._currentChannelId !== channelId) { @@ -449,21 +449,21 @@ export class LiveKitSession { // If we still have the room key from before disconnect, re-apply it now // so audio works immediately; the key holder will send a fresh offer if // the key was rotated during our absence. - // eslint-disable-next-line no-await-in-loop -- must set up E2EE before connect + // oxlint-disable-next-line no-await-in-loop -- must set up E2EE before connect this._ecdhKeyPair = await generateECDHKeyPair(); this._peerPublicKeys.clear(); if (this._roomKey) { - // eslint-disable-next-line no-await-in-loop -- must set key before connect + // oxlint-disable-next-line no-await-in-loop -- must set key before connect await this._e2eeKeyProvider.setKey(roomKeyToBase64(this._roomKey)); } - // eslint-disable-next-line no-await-in-loop -- must export before connect + // oxlint-disable-next-line no-await-in-loop -- must export before connect const reconnectPubKey = await exportPublicKey(this._ecdhKeyPair.publicKey); this.ws?.send({ type: "voice_e2ee_announce", payload: { public_key: reconnectPubKey }, }); - // eslint-disable-next-line no-await-in-loop -- sequential reconnect: must connect before restoring state + // oxlint-disable-next-line no-await-in-loop -- sequential reconnect: must connect before restoring state await newRoom.connect(resolvedUrl, token); if (signal.aborted || this._currentChannelId !== channelId) { @@ -488,7 +488,7 @@ export class LiveKitSession { newRoom .startAudio() .catch((err) => log.debug("Failed to start audio after reconnect", err)); - // eslint-disable-next-line no-await-in-loop -- sequential reconnect: must restore voice state after connect + // oxlint-disable-next-line no-await-in-loop -- sequential reconnect: must restore voice state after connect await this.restoreLocalVoiceState("reconnect"); // BUG-099: Reapply saved audio devices after reconnect (matches initial join path). const savedInput = loadPref("audioInputDevice", ""); @@ -907,7 +907,7 @@ export class LiveKitSession { for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) { try { - // eslint-disable-next-line no-await-in-loop -- sequential retry: must attempt connect before checking result + // oxlint-disable-next-line no-await-in-loop -- sequential retry: must attempt connect before checking result await localRoom.connect(resolvedUrl, token); // Checkpoint 2: after room.connect() — the primary race window. @@ -959,7 +959,7 @@ export class LiveKitSession { url: resolvedUrl, error: connectErr, }); - // eslint-disable-next-line no-await-in-loop -- intentional backoff delay between retry attempts + // oxlint-disable-next-line no-await-in-loop -- intentional backoff delay between retry attempts await new Promise((r) => setTimeout(r, RETRY_DELAY_MS)); // Generation check inside retry loop: a superseding join may arrive // during the backoff delay. @@ -1133,7 +1133,7 @@ export class LiveKitSession { ) { this.handleVoiceTokenRefresh(pToken); } else { - // eslint-disable-next-line no-await-in-loop -- sequential drain of pending joins to avoid unbounded recursion + // oxlint-disable-next-line no-await-in-loop -- sequential drain of pending joins to avoid unbounded recursion await this.connectAndSetup(pToken, pUrl, pChannelId, pDirectUrl, pIsKeyHolder); // If this attempt was itself superseded (another join arrived during the // await), the loop will naturally pick it up via the updated pendingJoin. diff --git a/Client/tauri-client/src/lib/logPersistence.ts b/Client/tauri-client/src/lib/logPersistence.ts index c4ce78a3..a6b3d45e 100644 --- a/Client/tauri-client/src/lib/logPersistence.ts +++ b/Client/tauri-client/src/lib/logPersistence.ts @@ -95,7 +95,7 @@ async function rotateOldFiles(): Promise { if (jsonlFiles.length > MAX_LOG_FILES) { const toRemove = jsonlFiles.slice(0, jsonlFiles.length - MAX_LOG_FILES); for (const file of toRemove) { - // eslint-disable-next-line no-await-in-loop -- sequential file deletion to avoid overwhelming the filesystem + // oxlint-disable-next-line no-await-in-loop -- sequential file deletion to avoid overwhelming the filesystem await remove(`${logDir}/${file}`); } } @@ -187,7 +187,7 @@ export async function readAllPersistedLogs(): Promise { const parts: string[] = []; for (const file of jsonlFiles) { - // eslint-disable-next-line no-await-in-loop -- files must be read in sorted order for correct log concatenation + // oxlint-disable-next-line no-await-in-loop -- files must be read in sorted order for correct log concatenation const content = await readTextFile(`${logDir}/${file}`); parts.push(content); } diff --git a/Client/tauri-client/src/lib/pluginBridge.ts b/Client/tauri-client/src/lib/pluginBridge.ts index 9629299a..c9e73809 100644 --- a/Client/tauri-client/src/lib/pluginBridge.ts +++ b/Client/tauri-client/src/lib/pluginBridge.ts @@ -109,7 +109,11 @@ class PluginBridge { this.postToFrame(pluginId, frame, { type, payload }); } - private postToFrame(pluginId: number, frame: HTMLIFrameElement, msg: { type: string; payload: unknown }): void { + private postToFrame( + pluginId: number, + frame: HTMLIFrameElement, + msg: { type: string; payload: unknown }, + ): void { // Restrict the postMessage target origin to the host page origin so a // navigated-away iframe (or one whose contentWindow has been swapped) // cannot receive host messages intended for a sandboxed plugin. The diff --git a/Client/tauri-client/src/lib/screenShare.ts b/Client/tauri-client/src/lib/screenShare.ts index a2229dab..e0d1e18a 100644 --- a/Client/tauri-client/src/lib/screenShare.ts +++ b/Client/tauri-client/src/lib/screenShare.ts @@ -209,7 +209,7 @@ export async function enableScreenshare( state.manualScreenTracks = screenTracks; for (const track of screenTracks) { const isVideo = track.kind === Track.Kind.Video; - // eslint-disable-next-line no-await-in-loop -- tracks must be published sequentially to maintain correct order + // oxlint-disable-next-line no-await-in-loop -- tracks must be published sequentially to maintain correct order await room.localParticipant.publishTrack(track, { source: isVideo ? Track.Source.ScreenShare : Track.Source.ScreenShareAudio, simulcast: false, diff --git a/Client/tauri-client/src/lib/solidAdapter.ts b/Client/tauri-client/src/lib/solidAdapter.ts index 5c35df7c..e99bc1ac 100644 --- a/Client/tauri-client/src/lib/solidAdapter.ts +++ b/Client/tauri-client/src/lib/solidAdapter.ts @@ -46,11 +46,7 @@ export function fromStoreSlice( ): Accessor { const initial = selector(store.getState()); const [value, setValue] = createSignal(initial, { equals: false }); - const unsub = store.subscribeSelector( - selector, - (next) => setValue(() => next), - isEqual, - ); + const unsub = store.subscribeSelector(selector, (next) => setValue(() => next), isEqual); onCleanup(unsub); return value; }