diff --git a/src/app/content/call-screen-view.tsx b/src/app/content/call-screen-view.tsx index ac93c6d..ea9c4cc 100644 --- a/src/app/content/call-screen-view.tsx +++ b/src/app/content/call-screen-view.tsx @@ -18,16 +18,9 @@ async function createScreenshot(): Promise { ) as HTMLVideoElement | null; if (!video) return null; - // Non-standard APIs are still the most concise way to capture a single frame. - // We fall back gracefully if the browser does not support them. - // @ts-expect-error – captureStream is not (yet) typed in lib.dom.d.ts - const track = video.captureStream?.().getVideoTracks?.()[0] as - | MediaStreamTrack - | undefined; - if (!track) return null; - // @ts-expect-error – ImageCapture is not (yet) typed in lib.dom.d.ts const imageCapture = new ImageCapture(track); + // @ts-expect-error grabFrame missing in TS typings const bitmap = await imageCapture.grabFrame(); const canvas = document.createElement("canvas"); diff --git a/src/app/content/conversion-screen-view.tsx b/src/app/content/conversion-screen-view.tsx index dc4de5e..cd31c60 100644 --- a/src/app/content/conversion-screen-view.tsx +++ b/src/app/content/conversion-screen-view.tsx @@ -17,6 +17,8 @@ export function ConversionScreenView() { const { session, setSession } = useSessionStore(); const { settings, setSettings } = useSettingsStore(); + const programResponseTag: string = "--Program Response--"; + const threadList = useRef(null); useEffect(() => { @@ -66,27 +68,64 @@ export function ConversionScreenView() { } function getNewMessageLine(mutation: MutationRecord) { - if (!mutation.addedNodes || mutation.addedNodes.length === 0) return; + if (!mutation.addedNodes || mutation.addedNodes.length === 0) { + logMessage("No added nodes found in mutation"); + return; + } const div = mutation.addedNodes[0]; - if (!(div instanceof HTMLDivElement)) return; + if (!div) { + return; + } + if (!(div instanceof HTMLDivElement)) { + return; + } + const divParent = div.parentElement; if (!divParent) return; + const children = Array.from(divParent.childNodes); if (children[children.length - 1] !== div) return; + // Look for the message container which has class 'html-div' + // This is the div that Facebook uses to display message content const messageContainer = div.querySelector( "div.html-div" ) as HTMLDivElement | null; - if (!messageContainer) return; + if (!messageContainer) { + return; + } + const parent = messageContainer.parentElement; - if (!parent) return; + if (!parent) { + logMessage("Message container has no parent element"); + return; + } - const messageLine = parent.childNodes[1] as HTMLDivElement | undefined; - if (!messageLine || (messageLine as any).dataset?.processed) return; - if (messageLine.childNodes.length <= 1) return; + // Get the actual message line (second child of parent) + const messageLine = parent.childNodes[1] as HTMLDivElement | undefined; + if (!messageLine) { + logMessage("Message line not found (no second child node)"); + return; + } + + if ((messageLine as any).dataset?.processed) { + logMessage("Message already processed (found processed flag)"); + return; + } + + if (messageLine.childNodes.length <= 1) { + logMessage("Message line has no content (empty message)"); + return; + } + + if (messageLine.textContent.includes(programResponseTag)) { + logMessage(`Message line {${messageLine.textContent}} is a program response. Do not process.`); + return; + } + if ( messageLine.previousSibling && - messageLine.previousSibling.textContent === "You sent" + messageLine.previousSibling.textContent != "You sent" ) return; @@ -235,18 +274,19 @@ export function ConversionScreenView() { } function enterMessage(message: string) { + const fullMessage = `*${programResponseTag}*\n${message}`; const messageInput = document.querySelector("div[aria-label='Message']"); if (!messageInput) { return; } - messageInput.innerHTML = message; + messageInput.innerHTML = fullMessage; messageInput.dispatchEvent(new Event("focus")); messageInput.dispatchEvent( new InputEvent("input", { bubbles: true, cancelable: true, - data: message, + data: fullMessage, inputType: "insertText", }) ); @@ -376,9 +416,6 @@ export function ConversionScreenView() { if (userScrolling) { stopChatMonitoring(); userScrolling = false; - } else { - // Programmatic scroll - console.log("programmatic scroll"); } }); return () => { diff --git a/src/app/content/index.tsx b/src/app/content/index.tsx index ebb55d8..3dd4666 100644 --- a/src/app/content/index.tsx +++ b/src/app/content/index.tsx @@ -10,11 +10,11 @@ import { CallScreenView } from "./call-screen-view"; import { ConversionScreenView } from "./conversion-screen-view"; const ContentScriptUI = () => { - const onTheCallScreen = document.location.href.includes(MESSENGER_CALL_URL); - const onTheConversationScreen = document.location.href.includes( - MESSENGER_CONVERSATION_URL - ); - + const currentUrl = document.location.href; + const onTheCallScreen = currentUrl.includes(MESSENGER_CALL_URL); + const onTheConversationScreen = currentUrl.includes(MESSENGER_CONVERSATION_URL) + && currentUrl.includes('/t'); + return (
{onTheConversationScreen && } diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 6ce998a..5219b58 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -68,7 +68,7 @@ export const providerInformation = { }; export const MESSENGER_CALL_URL = "groupcall/ROOM"; -export const MESSENGER_CONVERSATION_URL = "messages/t/"; +export const MESSENGER_CONVERSATION_URL = "messages"; export const aiChatProviders = [ "openai", diff --git a/src/lib/logos/11labs.tsx b/src/lib/logos/11labs.tsx index 5998a19..05408cb 100644 --- a/src/lib/logos/11labs.tsx +++ b/src/lib/logos/11labs.tsx @@ -17,8 +17,8 @@ export const ElevenLabsLogo = () => { y2="24" gradientUnits="userSpaceOnUse" > - - + + { y2="24" gradientUnits="userSpaceOnUse" > - - + + { y2="44.121" gradientUnits="userSpaceOnUse" > - - - - + + + + ); diff --git a/src/lib/logos/xai.tsx b/src/lib/logos/xai.tsx index 8d0ac93..a58dc16 100644 --- a/src/lib/logos/xai.tsx +++ b/src/lib/logos/xai.tsx @@ -11,27 +11,27 @@ export const XAILogo = () => { > );