mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
Signed-off-by: fyzanshaik <fyzan.shaik@gmail.com> Co-authored-by: Mahesh Sanikommmu <mahesh.svmr@gmail.com>
284 lines
7.3 KiB
TypeScript
284 lines
7.3 KiB
TypeScript
import {
|
|
DOMAINS,
|
|
ELEMENT_IDS,
|
|
MESSAGE_TYPES,
|
|
POSTHOG_EVENT_KEY,
|
|
} from "../../utils/constants"
|
|
import { trackEvent } from "../../utils/posthog"
|
|
import {
|
|
createTwitterImportButton,
|
|
createProjectSelectionModal,
|
|
DOMUtils,
|
|
} from "../../utils/ui-components"
|
|
|
|
async function loadSpaceGroteskFonts(): Promise<void> {
|
|
if (document.getElementById("supermemory-modal-styles")) {
|
|
return Promise.resolve()
|
|
}
|
|
|
|
const style = document.createElement("style")
|
|
style.id = "supermemory-modal-styles"
|
|
style.textContent = `
|
|
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300..700&display=swap');
|
|
`
|
|
document.head.appendChild(style)
|
|
|
|
await document.fonts.ready
|
|
}
|
|
|
|
export function initializeTwitter() {
|
|
if (!DOMUtils.isOnDomain(DOMAINS.TWITTER)) {
|
|
return
|
|
}
|
|
|
|
// Initial setup
|
|
if (window.location.pathname === "/i/bookmarks") {
|
|
setTimeout(() => {
|
|
addTwitterImportButton()
|
|
addTwitterImportButtonForFolders()
|
|
}, 2000)
|
|
} else {
|
|
// Remove button if not on bookmarks page
|
|
if (DOMUtils.elementExists(ELEMENT_IDS.TWITTER_IMPORT_BUTTON)) {
|
|
DOMUtils.removeElement(ELEMENT_IDS.TWITTER_IMPORT_BUTTON)
|
|
}
|
|
}
|
|
}
|
|
|
|
function addTwitterImportButton() {
|
|
if (window.location.pathname !== "/i/bookmarks") {
|
|
return
|
|
}
|
|
|
|
if (DOMUtils.elementExists(ELEMENT_IDS.TWITTER_IMPORT_BUTTON)) {
|
|
return
|
|
}
|
|
|
|
const button = createTwitterImportButton(async () => {
|
|
try {
|
|
await browser.runtime.sendMessage({
|
|
type: MESSAGE_TYPES.BATCH_IMPORT_ALL,
|
|
})
|
|
await trackEvent(POSTHOG_EVENT_KEY.TWITTER_IMPORT_STARTED, {
|
|
source: `${POSTHOG_EVENT_KEY.SOURCE}_content_script`,
|
|
})
|
|
} catch (error) {
|
|
console.error("Error starting import:", error)
|
|
}
|
|
})
|
|
|
|
document.body.appendChild(button)
|
|
}
|
|
|
|
function addTwitterImportButtonForFolders() {
|
|
if (window.location.pathname !== "/i/bookmarks") {
|
|
return
|
|
}
|
|
|
|
const targetElements = document.querySelectorAll(
|
|
".css-175oi2r.r-1wtj0ep.r-16x9es5.r-1mmae3n.r-o7ynqc.r-6416eg.r-1ny4l3l.r-1loqt21",
|
|
)
|
|
|
|
targetElements.forEach((element) => {
|
|
addButtonToElement(element as HTMLElement)
|
|
})
|
|
}
|
|
|
|
function addButtonToElement(element: HTMLElement) {
|
|
if (element.querySelector("[data-supermemory-button]")) {
|
|
return
|
|
}
|
|
|
|
loadSpaceGroteskFonts()
|
|
|
|
const button = createSaveTweetElement(async () => {
|
|
const url = element.getAttribute("href")
|
|
const bookmarkCollectionId = url?.split("/").pop()
|
|
console.log("Bookmark collection ID:", bookmarkCollectionId)
|
|
if (bookmarkCollectionId) {
|
|
await showProjectSelectionModal(bookmarkCollectionId)
|
|
}
|
|
})
|
|
|
|
button.setAttribute("data-supermemory-button", "true")
|
|
|
|
element.appendChild(button)
|
|
element.style.flexDirection = "row"
|
|
element.style.alignItems = "center"
|
|
element.style.justifyContent = "center"
|
|
element.style.gap = "10px"
|
|
element.style.padding = "10px"
|
|
}
|
|
|
|
export function updateTwitterImportUI(message: {
|
|
type: string
|
|
importedMessage?: string
|
|
totalImported?: number
|
|
}) {
|
|
const importButton = document.getElementById(
|
|
ELEMENT_IDS.TWITTER_IMPORT_BUTTON,
|
|
)
|
|
if (!importButton) return
|
|
|
|
const existingImg = importButton.querySelector("img")
|
|
if (existingImg) {
|
|
existingImg.remove()
|
|
const iconUrl = browser.runtime.getURL("/icon-16.png")
|
|
importButton.style.backgroundImage = `url("${iconUrl}")`
|
|
importButton.style.backgroundRepeat = "no-repeat"
|
|
importButton.style.backgroundSize = "20px 20px"
|
|
importButton.style.backgroundPosition = "8px center"
|
|
importButton.style.padding = "10px 16px 10px 32px"
|
|
}
|
|
|
|
let textSpan = importButton.querySelector(
|
|
"#sm-import-text",
|
|
) as HTMLSpanElement
|
|
if (!textSpan) {
|
|
textSpan = document.createElement("span")
|
|
textSpan.id = "sm-import-text"
|
|
textSpan.style.cssText = "font-weight: 500; font-size: 14px;"
|
|
importButton.appendChild(textSpan)
|
|
}
|
|
|
|
if (message.type === MESSAGE_TYPES.IMPORT_UPDATE) {
|
|
textSpan.textContent = message.importedMessage || ""
|
|
importButton.style.cursor = "default"
|
|
}
|
|
|
|
if (message.type === MESSAGE_TYPES.IMPORT_DONE) {
|
|
textSpan.textContent = `✓ Imported ${message.totalImported} tweets!`
|
|
textSpan.style.color = "#059669"
|
|
|
|
setTimeout(() => {
|
|
textSpan.textContent = "Import Bookmarks"
|
|
textSpan.style.color = ""
|
|
importButton.style.cursor = "pointer"
|
|
}, 3000)
|
|
}
|
|
}
|
|
|
|
export function handleTwitterNavigation() {
|
|
if (!DOMUtils.isOnDomain(DOMAINS.TWITTER)) {
|
|
return
|
|
}
|
|
|
|
if (window.location.pathname === "/i/bookmarks") {
|
|
addTwitterImportButton()
|
|
addTwitterImportButtonForFolders()
|
|
} else {
|
|
if (DOMUtils.elementExists(ELEMENT_IDS.TWITTER_IMPORT_BUTTON)) {
|
|
DOMUtils.removeElement(ELEMENT_IDS.TWITTER_IMPORT_BUTTON)
|
|
}
|
|
document.querySelectorAll("[data-supermemory-button]").forEach((button) => {
|
|
button.remove()
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Shows the project selection modal for folder imports
|
|
* @param bookmarkCollectionId - The ID of the bookmark collection to import
|
|
*/
|
|
async function showProjectSelectionModal(bookmarkCollectionId: string) {
|
|
try {
|
|
const modal = createProjectSelectionModal(
|
|
[],
|
|
async (selectedProject) => {
|
|
modal.remove()
|
|
|
|
try {
|
|
await browser.runtime.sendMessage({
|
|
type: MESSAGE_TYPES.BATCH_IMPORT_ALL,
|
|
isFolderImport: true,
|
|
bookmarkCollectionId: bookmarkCollectionId,
|
|
selectedProject: selectedProject,
|
|
})
|
|
} catch (error) {
|
|
console.error("Error importing bookmarks:", error)
|
|
}
|
|
},
|
|
() => {
|
|
modal.remove()
|
|
},
|
|
)
|
|
|
|
document.body.appendChild(modal)
|
|
|
|
try {
|
|
const response = await browser.runtime.sendMessage({
|
|
action: MESSAGE_TYPES.FETCH_PROJECTS,
|
|
})
|
|
|
|
if (response.success && response.data) {
|
|
const projects = response.data
|
|
|
|
if (projects.length === 0) {
|
|
console.warn("No projects available for import")
|
|
updateModalWithProjects(modal, [])
|
|
} else {
|
|
updateModalWithProjects(modal, projects)
|
|
}
|
|
} else {
|
|
console.error("Failed to fetch projects:", response.error)
|
|
updateModalWithProjects(modal, [])
|
|
}
|
|
} catch (error) {
|
|
console.error("Error fetching projects:", error)
|
|
updateModalWithProjects(modal, [])
|
|
}
|
|
} catch (error) {
|
|
console.error("Error showing project selection modal:", error)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the modal with fetched projects
|
|
* @param modal - The modal element
|
|
* @param projects - Array of projects to populate the dropdown
|
|
*/
|
|
function updateModalWithProjects(
|
|
modal: HTMLElement,
|
|
projects: Array<{ id: string; name: string; containerTag: string }>,
|
|
) {
|
|
const select = modal.querySelector("#project-select") as HTMLSelectElement
|
|
if (!select) return
|
|
|
|
while (select.children.length > 1) {
|
|
select.removeChild(select.children[1])
|
|
}
|
|
|
|
if (projects.length === 0) {
|
|
const noProjectsOption = document.createElement("option")
|
|
noProjectsOption.value = ""
|
|
noProjectsOption.textContent = "No projects available"
|
|
noProjectsOption.disabled = true
|
|
select.appendChild(noProjectsOption)
|
|
|
|
const importButton = modal.querySelector(
|
|
"button:last-child",
|
|
) as HTMLButtonElement
|
|
if (importButton) {
|
|
importButton.disabled = true
|
|
importButton.style.cssText = `
|
|
padding: 10px 16px;
|
|
border: none;
|
|
border-radius: 8px;
|
|
background: #d1d5db;
|
|
color: #9ca3af;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
cursor: not-allowed;
|
|
transition: all 0.2s ease;
|
|
`
|
|
}
|
|
} else {
|
|
projects.forEach((project) => {
|
|
const option = document.createElement("option")
|
|
option.value = project.id
|
|
option.textContent = project.name
|
|
option.dataset.containerTag = project.containerTag
|
|
select.appendChild(option)
|
|
})
|
|
}
|
|
}
|