Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 36 additions & 26 deletions src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
label: string; // for debug logging
}

class ApiTransactionManager {

Check warning on line 70 in src/background.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Mark these members as `readonly`.

See more on https://sonarcloud.io/project/issues?id=shouri123_Late-Meet&issues=AZ-AXPvy-TchFAS-SJCj&open=AZ-AXPvy-TchFAS-SJCj&pullRequest=887
private static instance: ApiTransactionManager | null = null;
private static readonly MAX_RETRIES = 5;
private static readonly BASE_DELAY_MS = 1_000;
Expand Down Expand Up @@ -426,8 +426,8 @@
isStoppingAudio = false;
isStartingAudio = false;
}
} catch {
// getContexts may fail if context is invalid; reset to be safe
} catch (err) {
console.debug("[LateMeet] Failed to query offscreen contexts:", err);
state.audioActive = false;
}
}
Expand Down Expand Up @@ -468,7 +468,8 @@
if (!url) return false;
try {
return new URL(url).hostname === "meet.google.com";
} catch {
} catch (err) {
console.debug("[LateMeet] Failed to parse URL in isMeetHostname:", err);
return false;
}
}
Expand Down Expand Up @@ -736,8 +737,8 @@
try {
// To popup/dashboard — ui truncated state
await chrome.runtime.sendMessage({ type: "STATE_UPDATE", state: uiData });
} catch {
/* ignore */
} catch (err) {
console.debug("[LateMeet] State broadcast to UI failed:", err);
}

try {
Expand All @@ -751,11 +752,13 @@
if (tab.id !== undefined) {
chrome.tabs
.sendMessage(tab.id, { type: "STATE_UPDATE", state: contentState })
.catch(() => {});
.catch((err) =>
console.debug("[LateMeet] State broadcast to content script failed:", err),
);
}
}
} catch {
/* ignore */
} catch (err) {
console.debug("[LateMeet] Content script query or broadcast failed:", err);
}

lastBroadcastTime = Date.now();
Expand Down Expand Up @@ -814,8 +817,8 @@
try {
const res = await chrome.runtime.sendMessage({ type: "OFFSCREEN_PING" });
if (res?.success) return;
} catch {
// ignore "Receiving end does not exist" message errors during early load
} catch (err) {
console.debug("[LateMeet] Offscreen ping failed during early load:", err);
}
await new Promise((resolve) => setTimeout(resolve, 30));
}
Expand Down Expand Up @@ -886,7 +889,7 @@
const estimatedSeconds = blob.size / 16000;
trackUsage({
elevenlabsSeconds: estimatedSeconds,
}).catch(() => {});
}).catch((err) => console.debug("[LateMeet] ElevenLabs usage tracking failed:", err));
const result = (data.text || "").trim();
if (!result) throw new Error("Empty ElevenLabs transcript");
return result;
Expand Down Expand Up @@ -934,7 +937,7 @@
if (data && typeof data.duration === "number") {
trackUsage({
whisperSeconds: data.duration,
}).catch(() => {});
}).catch((err) => console.debug("[LateMeet] Whisper usage tracking failed:", err));
}
return (data.text || "").trim();
});
Expand Down Expand Up @@ -991,7 +994,9 @@
completionTokens: data.usage.completion_tokens,
totalTokens: data.usage.total_tokens,
model: DEFAULT_CHAT_MODEL,
}).catch(() => {});
}).catch((err) =>
console.debug("[LateMeet] Transcript refinement usage tracking failed:", err),
);
}
const refined = data?.choices?.[0]?.message?.content?.trim() || rawText;

Expand Down Expand Up @@ -1193,7 +1198,7 @@
completionTokens: data.usage.completion_tokens,
totalTokens: data.usage.total_tokens,
model: settings.aiModel || DEFAULT_CHAT_MODEL,
}).catch(() => {});
}).catch((err) => console.debug("[LateMeet] Summarization usage tracking failed:", err));
}
const result = data?.choices?.[0]?.message?.content;
if (!result) throw new Error("Empty summarization response");
Expand Down Expand Up @@ -1359,7 +1364,9 @@
await broadcastStateUpdate();
},
onDrain: () => {
chrome.runtime.sendMessage({ type: "OFFSCREEN_RESUME_RECORDING" }).catch(() => {});
chrome.runtime
.sendMessage({ type: "OFFSCREEN_RESUME_RECORDING" })
.catch((err) => console.debug("[LateMeet] Resume recording notification failed:", err));
},
});

Expand Down Expand Up @@ -1461,11 +1468,12 @@
completionTokens: data.usage.completion_tokens,
totalTokens: data.usage.total_tokens,
model: DEFAULT_CHAT_MODEL,
}).catch(() => {});
}).catch((err) => console.debug("[LateMeet] Late-joiner usage tracking failed:", err));
}
return data?.choices?.[0]?.message?.content?.trim() || fallback;
});
} catch {
} catch (err) {
console.debug("[LateMeet] Late-joiner greeting failed:", err);
return fallback;
}
}
Expand Down Expand Up @@ -1770,8 +1778,8 @@
`[LateMeet] Offscreen drain summary: complete=${!!response.drainComplete} processed=${response.chunksProcessed ?? 0} dropped=${response.chunksDropped ?? 0} pending=${response.chunksPending ?? 0}`,
);
}
} catch {
// Ignore if offscreen not running
} catch (err) {
console.debug("[LateMeet] Offscreen drain ping failed (offscreen may not be running):", err);
}
}

Expand All @@ -1790,8 +1798,8 @@
break;
}
}
} catch {
// Offscreen may have closed; stop polling
} catch (err) {
console.debug("[LateMeet] Offscreen poll failed (may have closed):", err);
break;
}
await new Promise((resolve) => setTimeout(resolve, 200));
Expand Down Expand Up @@ -1834,8 +1842,8 @@
if (stopPlan.shouldNotifySessionEnded) {
try {
await chrome.runtime.sendMessage({ type: "SESSION_ENDED" });
} catch {
// no listeners
} catch (err) {
console.debug("[LateMeet] SESSION_ENDED message failed:", err);
}
}

Expand All @@ -1862,8 +1870,8 @@
await broadcastStateUpdate(true);
}
}
} catch {
// invalid URL — ignore silently
} catch (err) {
console.debug("[LateMeet] Failed to handle tab URL:", err);
}
});

Expand Down Expand Up @@ -2353,7 +2361,9 @@
summaryInFlight,
selfParticipantName,
};
chrome.storage.local.set({ activeMeetingGuards: guards }).catch(() => {});
chrome.storage.local
.set({ activeMeetingGuards: guards })
.catch((err) => console.debug("[LateMeet] Flush guards failed:", err));
});

// Proactive scan on startup/load
Expand Down
20 changes: 11 additions & 9 deletions src/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,16 +441,16 @@ void initTheme().catch((err) => console.error(err));
if (participantPollTimer) return;

participantPollTimer = setInterval(async () => {
const { participants, selfName } = await collectParticipants();

try {
const { participants, selfName } = await collectParticipants();

await chrome.runtime.sendMessage({
type: "PARTICIPANTS_UPDATED",
participants,
selfName,
});
} catch {
// Service worker idle
} catch (err) {
console.debug("[LateMeet] Participant polling failed:", err);
}
}, 5000);
}
Expand Down Expand Up @@ -480,8 +480,8 @@ void initTheme().catch((err) => console.error(err));
name,
});
lastActiveSpeakerName = name;
} catch {
// Service worker idle
} catch (err) {
console.debug("[LateMeet] Active speaker publish failed:", err);
}
}

Expand Down Expand Up @@ -672,9 +672,11 @@ void initTheme().catch((err) => console.error(err));
globalThis.addEventListener("beforeunload", () => {
// 1. Attempt auto-save first, while the runtime is still reachable.
try {
chrome.runtime.sendMessage({ type: "SAVE_SESSION" }).catch(() => {});
} catch {
// Ignore — page is already unloading
chrome.runtime
.sendMessage({ type: "SAVE_SESSION" })
.catch((err) => console.debug("[LateMeet] Session save failed:", err));
} catch (err) {
console.debug("[LateMeet] SAVE_SESSION send failed (page unloading):", err);
}
// 2. Tear down observers and timers after save is dispatched.
destroyAll();
Expand Down
17 changes: 11 additions & 6 deletions src/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ function isMeetHostname(url: string | null | undefined): boolean {
if (!url) return false;
try {
return new URL(url).hostname === "meet.google.com";
} catch {
} catch (err) {
console.debug("[LateMeet] Failed to parse hostname:", err);
return false;
}
}
Expand Down Expand Up @@ -319,8 +320,8 @@ document.addEventListener("DOMContentLoaded", async () => {
try {
lastState = await chrome.runtime.sendMessage({ type: "GET_STATE" });
if (lastState) updateDashboard(lastState);
} catch {
/* no meeting data yet */
} catch (err) {
console.debug("[LateMeet] Initial GET_STATE failed (no meeting data yet):", err);
}

// ——— Listen for State Updates ———
Expand Down Expand Up @@ -372,8 +373,11 @@ document.addEventListener("DOMContentLoaded", async () => {
const micStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
micStream.getTracks().forEach((t) => t.stop());
return true;
} catch {
console.warn("[Dashboard] Mic permission not granted — waveform will use tab audio only");
} catch (err) {
console.warn(
"[Dashboard] Mic permission not granted — waveform will use tab audio only:",
err,
);
return false;
}
}
Expand Down Expand Up @@ -2065,7 +2069,8 @@ document.addEventListener("DOMContentLoaded", async () => {
}
await navigator.clipboard.writeText(text);
showToast("Summary copied to clipboard!", "success");
} catch {
} catch (err) {
console.warn("[Dashboard] Failed to copy summary:", err);
showToast("Failed to copy summary", "error");
}
});
Expand Down
7 changes: 5 additions & 2 deletions src/dashboardCapture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ export async function startDashboardAudioCapture({
let microphoneEnabled = false;
try {
microphoneEnabled = await requestMicrophonePermission();
} catch {
// Microphone capture is optional; the offscreen document can still record tab audio.
} catch (err) {
console.debug(
"[LateMeet] Microphone permission request failed (optional capture continues):",
err,
);
}

const response = await startAudioCapture({
Expand Down
6 changes: 4 additions & 2 deletions src/meetingTabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ export function getMeetingIdFromUrl(url: string | undefined): string | null {
if (!MEET_ID_REGEX.test(meetingId)) return null;

return meetingId;
} catch {
} catch (err) {
console.debug("[LateMeet] Failed to parse meeting URL:", err);
return null;
}
}
Expand Down Expand Up @@ -61,7 +62,8 @@ export async function resolveManualMeetTab(): Promise<MeetTabSelection> {
export async function resolveDetectedMeetTab(): Promise<MeetTabSelection | null> {
try {
return await resolveManualMeetTab();
} catch {
} catch (err) {
console.debug("[LateMeet] Failed to resolve meet tab:", err);
return null;
}
}
14 changes: 10 additions & 4 deletions src/offscreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ let voiceActivity = new VoiceActivityTracker({
// open than the offscreen DevTools.
function relay(message: string) {
console.log(`[LateMeet][offscreen] ${message}`);
chrome.runtime.sendMessage({ type: "OFFSCREEN_LOG", message }).catch(() => {});
chrome.runtime
.sendMessage({ type: "OFFSCREEN_LOG", message })
.catch((err) => console.debug("[LateMeet][offscreen] Relay log send failed:", err));
}

function blobToBase64(blob: Blob): Promise<string> {
Expand Down Expand Up @@ -135,7 +137,9 @@ function sampleAndSendWaveform() {
buckets.push(Math.min(1, (sum / bucketSize) * WAVEFORM_GAIN));
}

chrome.runtime.sendMessage({ type: "WAVEFORM_DATA", buckets }).catch(() => {});
chrome.runtime
.sendMessage({ type: "WAVEFORM_DATA", buckets })
.catch((err) => console.debug("[LateMeet][offscreen] Waveform data send failed:", err));
}

async function flushAudioChunk(force = false) {
Expand Down Expand Up @@ -194,7 +198,7 @@ async function flushAudioChunk(force = false) {
type: "UNEXPECTED_TRACK_END",
reason: "Recorder failed to restart after flush",
})
.catch(() => {});
.catch((err) => console.debug("[LateMeet][offscreen] Track end notification failed:", err));
return;
}

Expand Down Expand Up @@ -514,7 +518,9 @@ async function startCapture(
type: "UNEXPECTED_TRACK_END",
reason: "Track ended unexpectedly (tab closed or mic disconnected)",
})
.catch(() => {});
.catch((err) =>
console.debug("[LateMeet][offscreen] Track end notification failed:", err),
);
}
};
});
Expand Down
8 changes: 4 additions & 4 deletions src/popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ document.addEventListener("DOMContentLoaded", async () => {
const micStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
micStream.getTracks().forEach((track) => track.stop());
return true;
} catch {
console.warn("[LateMeet] Microphone permission not granted — recording tab audio only");
} catch (err) {
console.warn("[LateMeet] Microphone permission not granted — recording tab audio only:", err);
return false;
}
}
Expand Down Expand Up @@ -597,8 +597,8 @@ document.addEventListener("DOMContentLoaded", async () => {
try {
lastState = await chrome.runtime.sendMessage({ type: "GET_STATE" });
if (lastState) updateUI(lastState);
} catch {
/* background script might be idle */
} catch (err) {
console.debug("[LateMeet] Initial GET_STATE failed (background script may be idle):", err);
}

// ——— Listen for State Updates ———
Expand Down
3 changes: 2 additions & 1 deletion src/popupCapture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export async function startPopupAudioCapture({
let microphoneEnabled: boolean;
try {
microphoneEnabled = await requestMicrophonePermission();
} catch {
} catch (err) {
console.debug("[LateMeet] Microphone permission request failed:", err);
microphoneEnabled = false;
}

Expand Down
Loading