diff --git a/apps/extension/background.ts b/apps/extension/background.ts index 3ecb26fd..bfe27763 100644 --- a/apps/extension/background.ts +++ b/apps/extension/background.ts @@ -18,7 +18,7 @@ const BACKEND_URL = "https://beta.supermemory.ai"; // This is to prevent going over the rate limit let lastTwitterFetch = 0; -const batchImportAll = async (cursor = "") => { +const batchImportAll = async (cursor = "", totalImported = 0) => { chrome.storage.session.get(["cookie", "csrf", "auth"], (result) => { if (!result.cookie || !result.csrf || !result.auth) { console.log("cookie, csrf, or auth is missing"); @@ -37,12 +37,11 @@ const batchImportAll = async (cursor = "") => { }; const variables = { - count: 100, // Using 100 as the count to prevent rate limiting + count: 100, cursor: cursor, includePromotedContent: false, }; - // Append cursor if present const urlWithCursor = cursor ? `${BOOKMARKS_URL}&variables=${encodeURIComponent(JSON.stringify(variables))}` : BOOKMARKS_URL; @@ -51,6 +50,7 @@ const batchImportAll = async (cursor = "") => { .then((response) => response.json()) .then((data) => { const tweets = getAllTweets(data); + let importedCount = 0; for (const tweet of tweets) { console.log(tweet); @@ -74,16 +74,23 @@ const batchImportAll = async (cursor = "") => { description: tweet.text.slice(0, 100), type: "tweet", }), - }).then((ers) => console.log(ers.status)); + }).then((ers) => { + console.log(ers.status); + importedCount++; + totalImported++; + // Send an update message to the content script + chrome.runtime.sendMessage({ + type: "import-update", + importedCount: totalImported, + }); + }); }); })(); } console.log("tweets", tweets); - console.log("data", data); - // Extract next cursor const instructions = data.data?.bookmark_timeline_v2?.timeline?.instructions; const lastInstruction = instructions?.[0].entries.pop(); @@ -92,7 +99,6 @@ const batchImportAll = async (cursor = "") => { let nextCursor = lastInstruction?.content?.value; if (!nextCursor) { - // Find the nextcursor in the entire instructions array for (let i = instructions.length - 1; i >= 0; i--) { if (instructions[i].entryId.startsWith("cursor-bottom-")) { nextCursor = instructions[i].content.value; @@ -102,16 +108,22 @@ const batchImportAll = async (cursor = "") => { } if (nextCursor) { - batchImportAll(nextCursor); // Recursively call with new cursor + batchImportAll(nextCursor, totalImported); // Recursively call with new cursor } else { - // No more cursors, run final function console.log("All bookmarks imported"); - // Run function maybe + // Send a "done" message to the content script + chrome.runtime.sendMessage({ + type: "import-done", + importedCount: totalImported, + }); } } else { - // No cursor-bottom-* found, run final function console.log("All bookmarks imported"); - // Run function maybe + // Send a "done" message to the content script + chrome.runtime.sendMessage({ + type: "import-done", + importedCount: totalImported, + }); } }) .catch((error) => console.error(error)); diff --git a/apps/extension/content/ContentApp.tsx b/apps/extension/content/ContentApp.tsx index ee1fd6d4..4fe2bc66 100644 --- a/apps/extension/content/ContentApp.tsx +++ b/apps/extension/content/ContentApp.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from "react"; import { Readability } from "@mozilla/readability"; +import tailwindBg from "../public/tailwind_bg.png"; export default function ContentApp({ token }: { token: string | undefined }) { const [text, setText] = useState(""); @@ -7,16 +8,10 @@ export default function ContentApp({ token }: { token: string | undefined }) { const [loading, setLoading] = useState(false); - const [isTwitterBookmarksEnabled, setIsTwitterBookmarksEnabled] = - useState(false); + const [importedCount, setImportedCount] = useState(0); + const [isImporting, setIsImporting] = useState(false); useEffect(() => { - const messageListener = (message: any) => { - setText(message); - setTimeout(() => setText(""), 2000); - }; - chrome.runtime.onMessage.addListener(messageListener); - document.addEventListener("mousemove", (e) => { const percentageX = (e.clientX / window.innerWidth) * 100; const percentageY = (e.clientY / window.innerHeight) * 100; @@ -45,8 +40,22 @@ export default function ContentApp({ token }: { token: string | undefined }) { getUserData(); + chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + console.log("request", request); + console.log("sender", sender); + console.log("sendResponse", sendResponse); + if (request.type === "import-update") { + setIsImporting(true); + setImportedCount(request.importedCount); + } + + if (request.type === "import-done") { + setIsImporting(false); + } + }); + return () => { - chrome.runtime.onMessage.removeListener(messageListener); + document.removeEventListener("mousemove", () => {}); }; }, []); @@ -116,74 +125,55 @@ export default function ContentApp({ token }: { token: string | undefined }) { )} - - - {(window.location.href === "https://twitter.com" || - window.location.href === "https://x.com") && - (isTwitterBookmarksEnabled ? ( - - ) : ( - <> - - - ))} + + +
+

+ Your twitter bookmarks are being imported. +

+

+ This is done completely locally, so please keep this tab open! +

+
+ Imported {importedCount} bookmarks + + + )} + + {(window.location.host === "twitter.com" || + window.location.host === "x.com") && ( + + )} ); } diff --git a/apps/extension/manifest.json b/apps/extension/manifest.json index b898cb0b..bb537205 100644 --- a/apps/extension/manifest.json +++ b/apps/extension/manifest.json @@ -18,8 +18,8 @@ }, "web_accessible_resources": [ { - "resources": ["public/*"], - "matches": ["http://*/*", "https://*/*"] + "resources": ["public/*/**"], + "matches": [""] } ], "permissions": ["webRequest", "storage"],