Skip to content
9 changes: 1 addition & 8 deletions src/app/content/call-screen-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,9 @@ async function createScreenshot(): Promise<string | null> {
) 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");
Expand Down
63 changes: 50 additions & 13 deletions src/app/content/conversion-screen-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export function ConversionScreenView() {
const { session, setSession } = useSessionStore();
const { settings, setSettings } = useSettingsStore();

const programResponseTag: string = "--Program Response--";

const threadList = useRef<HTMLDivElement | null>(null);

useEffect(() => {
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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",
})
);
Expand Down Expand Up @@ -376,9 +416,6 @@ export function ConversionScreenView() {
if (userScrolling) {
stopChatMonitoring();
userScrolling = false;
} else {
// Programmatic scroll
console.log("programmatic scroll");
}
});
return () => {
Expand Down
10 changes: 5 additions & 5 deletions src/app/content/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div className="fixed bottom-0 flex flex-col gap-4 p-4">
{onTheConversationScreen && <ConversionScreenView />}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
8 changes: 4 additions & 4 deletions src/lib/logos/11labs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ export const ElevenLabsLogo = () => {
y2="24"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stop-color="#41474a"></stop>
<stop offset="1" stop-color="#323538"></stop>
<stop offset="0" stopColor="#41474a"></stop>
<stop offset="1" stopColor="#323538"></stop>
</linearGradient>
<path
fill="url(#wcu9za2JCL5_IXX0lZWPca_kQSS04V7DmPz_gr1)"
Expand All @@ -32,8 +32,8 @@ export const ElevenLabsLogo = () => {
y2="24"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stop-color="#41474a"></stop>
<stop offset="1" stop-color="#323538"></stop>
<stop offset="0" stopColor="#41474a"></stop>
<stop offset="1" stopColor="#323538"></stop>
</linearGradient>
<path
fill="url(#wcu9za2JCL5_IXX0lZWPcb_kQSS04V7DmPz_gr2)"
Expand Down
12 changes: 6 additions & 6 deletions src/lib/logos/perplexity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ export const PerplexityLogo = () => {
y2="44.121"
gradientUnits="userSpaceOnUse"
>
<stop offset=".002" stop-color="#9c55d4"></stop>
<stop offset=".003" stop-color="#20808d"></stop>
<stop offset=".373" stop-color="#218f9b"></stop>
<stop offset="1" stop-color="#22b1bc"></stop>
<stop offset=".002" stopColor="#9c55d4"></stop>
<stop offset=".003" stopColor="#20808d"></stop>
<stop offset=".373" stopColor="#218f9b"></stop>
<stop offset="1" stopColor="#22b1bc"></stop>
</linearGradient>
<path
fill="url(#f1cRcgrFgpE5Wk07TriTIa_kzJWN5jCDzpq_gr1)"
fill-rule="evenodd"
fillRule="evenodd"
d="M11.469,4l11.39,10.494v-0.002V4.024h2.217v10.517 L36.518,4v11.965h4.697v17.258h-4.683v10.654L25.077,33.813v10.18h-2.217V33.979L11.482,44V33.224H6.785V15.965h4.685V4z M21.188,18.155H9.002v12.878h2.477v-4.062L21.188,18.155z M13.699,27.943v11.17l9.16-8.068V19.623L13.699,27.943z M25.141,30.938 V19.612l9.163,8.321v5.291h0.012v5.775L25.141,30.938z M36.532,31.033h2.466V18.155H26.903l9.629,8.725V31.033z M34.301,15.965 V9.038l-7.519,6.927H34.301z M21.205,15.965h-7.519V9.038L21.205,15.965z"
clip-rule="evenodd"
clipRule="evenodd"
></path>
</svg>
);
Expand Down
16 changes: 8 additions & 8 deletions src/lib/logos/xai.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@ export const XAILogo = () => {
>
<polygon
fill="#212121"
fill-rule="evenodd"
fillRule="evenodd"
points="24.032,28.919 40.145,5.989 33.145,5.989 20.518,23.958"
clip-rule="evenodd"
clipRule="evenodd"
></polygon>
<polygon
fill="#212121"
fill-rule="evenodd"
fillRule="evenodd"
points="14.591,32.393 7.145,42.989 14.145,42.989 18.105,37.354"
clip-rule="evenodd"
clipRule="evenodd"
></polygon>
<polygon
fill="#212121"
fill-rule="evenodd"
fillRule="evenodd"
points="14.547,18.989 7.547,18.989 24.547,42.989 31.547,42.989"
clip-rule="evenodd"
clipRule="evenodd"
></polygon>
<polygon
fill="#212121"
fill-rule="evenodd"
fillRule="evenodd"
points="35,16.789 35,43 41,43 41,8.251"
clip-rule="evenodd"
clipRule="evenodd"
></polygon>
</svg>
);
Expand Down