mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-09-06 08:16:03 +00:00
updated few more issues
This commit is contained in:
parent
2be9d04fdc
commit
b41ef4bb4b
16 changed files with 196 additions and 167 deletions
|
|
@ -1,4 +1,9 @@
|
|||
import { DOMAINS, ELEMENT_IDS, MESSAGE_TYPES } from "../utils/constants"
|
||||
import {
|
||||
DOMAINS,
|
||||
ELEMENT_IDS,
|
||||
MESSAGE_TYPES,
|
||||
STORAGE_KEYS,
|
||||
} from "../utils/constants"
|
||||
import {
|
||||
createChatGPTInputBarElement,
|
||||
createSaveTweetElement,
|
||||
|
|
@ -261,8 +266,8 @@ export default defineContentScript({
|
|||
isTwitterImportOpen = true
|
||||
|
||||
// Check if user is authenticated
|
||||
browser.storage.local.get(["bearerToken"], ({ bearerToken }) => {
|
||||
const isAuthenticated = !!bearerToken
|
||||
browser.storage.local.get([STORAGE_KEYS.BEARER_TOKEN], (result) => {
|
||||
const isAuthenticated = !!result[STORAGE_KEYS.BEARER_TOKEN]
|
||||
|
||||
twitterImportUI = createTwitterImportUI(
|
||||
hideTwitterImportUI,
|
||||
|
|
@ -297,10 +302,10 @@ export default defineContentScript({
|
|||
}) {
|
||||
if (!isTwitterImportOpen || !twitterImportUI) return
|
||||
|
||||
const statusDiv = twitterImportUI.querySelector("#twitter-import-status")
|
||||
const button = twitterImportUI.querySelector("#twitter-import-button")
|
||||
const statusDiv = twitterImportUI.querySelector(`#${ELEMENT_IDS.TWITTER_IMPORT_STATUS}`)
|
||||
const button = twitterImportUI.querySelector(`#${ELEMENT_IDS.TWITTER_IMPORT_BTN}`)
|
||||
|
||||
if (message.type === "import-update") {
|
||||
if (message.type === MESSAGE_TYPES.IMPORT_UPDATE) {
|
||||
if (statusDiv) {
|
||||
statusDiv.innerHTML = `
|
||||
<div style="display: flex; align-items: center; gap: 8px; color: #92400e; background: #fef3c7; border: 1px solid #f59e0b; border-radius: 8px; padding: 8px 12px; font-size: 13px;">
|
||||
|
|
@ -315,7 +320,7 @@ export default defineContentScript({
|
|||
}
|
||||
}
|
||||
|
||||
if (message.type === "import-done") {
|
||||
if (message.type === MESSAGE_TYPES.IMPORT_DONE) {
|
||||
if (statusDiv) {
|
||||
statusDiv.innerHTML = `
|
||||
<div style="display: flex; align-items: center; gap: 8px; color: #0369a1; background: #f0f9ff; border: 1px solid #0ea5e9; border-radius: 8px; padding: 8px 12px; font-size: 13px;">
|
||||
|
|
@ -449,7 +454,9 @@ export default defineContentScript({
|
|||
return
|
||||
}
|
||||
|
||||
chrome.storage.local.set({ bearerToken }, () => {})
|
||||
chrome.storage.local.set({
|
||||
[STORAGE_KEYS.BEARER_TOKEN]: bearerToken,
|
||||
}, () => {})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,41 +1,40 @@
|
|||
import { useQueryClient } from "@tanstack/react-query"
|
||||
import { useEffect, useState } from "react"
|
||||
import "./App.css"
|
||||
import { STORAGE_KEYS } from "../../utils/constants"
|
||||
import {
|
||||
getDefaultProject,
|
||||
getProjects,
|
||||
setDefaultProject,
|
||||
} from "../../utils/api"
|
||||
useDefaultProject,
|
||||
useProjects,
|
||||
useSetDefaultProject,
|
||||
} from "../../utils/query-hooks"
|
||||
import type { Project } from "../../utils/types"
|
||||
|
||||
function App() {
|
||||
const [userSignedIn, setUserSignedIn] = useState<boolean>(false)
|
||||
const [loading, setLoading] = useState<boolean>(true)
|
||||
const [projects, setProjects] = useState<Project[]>([])
|
||||
const [defaultProject, setDefaultProjectState] = useState<Project | null>(
|
||||
null,
|
||||
)
|
||||
const [loadingProjects, setLoadingProjects] = useState<boolean>(false)
|
||||
const [showProjectSelector, setShowProjectSelector] = useState<boolean>(false)
|
||||
const [currentUrl, setCurrentUrl] = useState<string>("")
|
||||
const [currentTitle, setCurrentTitle] = useState<string>("")
|
||||
const [saving, setSaving] = useState<boolean>(false)
|
||||
const [activeTab, setActiveTab] = useState<"save" | "imports">("save")
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const { data: projects = [], isLoading: loadingProjects } = useProjects({
|
||||
enabled: userSignedIn,
|
||||
})
|
||||
const { data: defaultProject } = useDefaultProject({
|
||||
enabled: userSignedIn,
|
||||
})
|
||||
const setDefaultProjectMutation = useSetDefaultProject()
|
||||
|
||||
useEffect(() => {
|
||||
const checkAuthStatus = async () => {
|
||||
try {
|
||||
const result = await chrome.storage.local.get(["bearerToken"])
|
||||
const isSignedIn = !!result.bearerToken
|
||||
const result = await chrome.storage.local.get([
|
||||
STORAGE_KEYS.BEARER_TOKEN,
|
||||
])
|
||||
const isSignedIn = !!result[STORAGE_KEYS.BEARER_TOKEN]
|
||||
setUserSignedIn(isSignedIn)
|
||||
|
||||
if (isSignedIn) {
|
||||
try {
|
||||
const defaultProj = await getDefaultProject()
|
||||
setDefaultProjectState(defaultProj)
|
||||
} catch (error) {
|
||||
console.error("Error loading default project:", error)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error checking auth status:", error)
|
||||
setUserSignedIn(false)
|
||||
|
|
@ -63,44 +62,28 @@ function App() {
|
|||
getCurrentTab()
|
||||
}, [])
|
||||
|
||||
const loadProjects = async () => {
|
||||
setLoadingProjects(true)
|
||||
try {
|
||||
const projectsList = await getProjects()
|
||||
setProjects(projectsList)
|
||||
console.log("Projects:", projectsList)
|
||||
console.log("Default project:", defaultProject)
|
||||
// If no default project is set and projects are available, set first as default
|
||||
if (!defaultProject && projectsList.length > 0) {
|
||||
const firstProject = projectsList[0]
|
||||
await setDefaultProject(firstProject)
|
||||
setDefaultProjectState(firstProject)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading projects:", error)
|
||||
} finally {
|
||||
setLoadingProjects(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleProjectSelect = async (project: Project) => {
|
||||
try {
|
||||
await setDefaultProject(project)
|
||||
setDefaultProjectState(project)
|
||||
setShowProjectSelector(false)
|
||||
} catch (error) {
|
||||
console.error("Error setting default project:", error)
|
||||
}
|
||||
const handleProjectSelect = (project: Project) => {
|
||||
setDefaultProjectMutation.mutate(project, {
|
||||
onSuccess: () => {
|
||||
setShowProjectSelector(false)
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error("Error setting default project:", error)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const handleShowProjectSelector = () => {
|
||||
console.log("handleShowProjectSelector, projects.length:", projects.length)
|
||||
if (projects.length === 0) {
|
||||
loadProjects()
|
||||
}
|
||||
setShowProjectSelector(true)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!defaultProject && projects.length > 0) {
|
||||
const firstProject = projects[0]
|
||||
setDefaultProjectMutation.mutate(firstProject)
|
||||
}
|
||||
}, [defaultProject, projects, setDefaultProjectMutation])
|
||||
|
||||
const handleSaveCurrentPage = async () => {
|
||||
setSaving(true)
|
||||
try {
|
||||
|
|
@ -122,10 +105,9 @@ function App() {
|
|||
|
||||
const handleSignOut = async () => {
|
||||
try {
|
||||
await chrome.storage.local.remove(["bearerToken"])
|
||||
await chrome.storage.local.remove([STORAGE_KEYS.BEARER_TOKEN])
|
||||
setUserSignedIn(false)
|
||||
setDefaultProjectState(null)
|
||||
setProjects([])
|
||||
queryClient.clear()
|
||||
} catch (error) {
|
||||
console.error("Error signing out:", error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { QueryClientProvider } from "@tanstack/react-query"
|
||||
import React from "react"
|
||||
import ReactDOM from "react-dom/client"
|
||||
import { queryClient } from "../../utils/query-client"
|
||||
import App from "./App.js"
|
||||
import "./style.css"
|
||||
|
||||
|
|
@ -7,7 +9,9 @@ const rootElement = document.getElementById("root")
|
|||
if (rootElement) {
|
||||
ReactDOM.createRoot(rootElement).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<App />
|
||||
</QueryClientProvider>
|
||||
</React.StrictMode>,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { QueryClientProvider } from "@tanstack/react-query"
|
||||
import React from "react"
|
||||
import ReactDOM from "react-dom/client"
|
||||
import { queryClient } from "../../utils/query-client"
|
||||
import Welcome from "./Welcome"
|
||||
import "./welcome.css"
|
||||
|
||||
|
|
@ -7,7 +9,9 @@ const rootElement = document.getElementById("root")
|
|||
if (rootElement) {
|
||||
ReactDOM.createRoot(rootElement).render(
|
||||
<React.StrictMode>
|
||||
<Welcome />
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<Welcome />
|
||||
</QueryClientProvider>
|
||||
</React.StrictMode>,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"postinstall": "wxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^5.85.5",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0"
|
||||
},
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.7 KiB |
|
|
@ -1,15 +0,0 @@
|
|||
<svg width="1138" height="135" viewBox="0 0 1138 135" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M267.914 105.886C258.2 105.886 250.229 103.796 244.024 99.6159C237.808 95.4359 234.055 89.4661 232.753 81.6949L250.183 77.2146C250.88 80.7019 252.065 83.4385 253.715 85.4246C255.365 87.4222 257.422 88.831 259.873 89.6855C262.325 90.5284 265.009 90.9556 267.914 90.9556C272.318 90.9556 275.571 90.182 277.675 88.6462C279.778 87.0989 280.835 85.1937 280.835 82.8958C280.835 80.5979 279.836 78.8428 277.826 77.5957C275.815 76.3486 272.62 75.3325 268.205 74.5357L263.998 73.7852C258.793 72.7921 254.029 71.418 249.729 69.6744C245.419 67.9308 241.968 65.5175 239.365 62.4344C236.762 59.3513 235.461 55.3676 235.461 50.4947C235.461 43.1277 238.168 37.4812 243.571 33.5436C248.986 29.6176 256.085 27.6431 264.905 27.6431C273.213 27.6431 280.126 29.4906 285.634 33.1626C291.142 36.8461 294.744 41.6728 296.452 47.6426L278.871 53.012C278.07 49.2361 276.443 46.5456 273.991 44.9521C271.539 43.3586 268.507 42.5619 264.905 42.5619C261.303 42.5619 258.537 43.1854 256.643 44.4325C254.737 45.6796 253.785 47.4001 253.785 49.5825C253.785 51.9727 254.784 53.7394 256.794 54.8826C258.793 56.0258 261.5 56.9033 264.905 57.4922L269.111 58.2428C274.723 59.2358 279.801 60.5522 284.356 62.2034C288.911 63.8431 292.513 66.1872 295.174 69.2241C297.823 72.2609 299.159 76.3717 299.159 81.5448C299.159 89.3044 296.324 95.3089 290.665 99.5351C285.007 103.773 277.419 105.886 267.903 105.886H267.914Z" fill="#1C2026"/>
|
||||
<path d="M332.159 105.585C326.35 105.585 321.272 104.269 316.914 101.624C312.557 98.9915 309.176 95.3311 306.77 90.6545C304.365 85.978 303.168 80.597 303.168 74.5348V30.3442H322.097V73.0453C322.097 78.6225 323.468 82.8025 326.233 85.5854C328.987 88.3682 332.915 89.7654 338.027 89.7654C343.837 89.7654 348.345 87.8486 351.552 84.015C354.759 80.1813 356.363 74.8351 356.363 67.9646V30.3442H375.291V104.396H356.665V94.696H353.958C352.761 97.1902 350.507 99.6266 347.195 102.017C343.895 104.407 338.875 105.596 332.171 105.596L332.159 105.585Z" fill="#1C2026"/>
|
||||
<path d="M388.805 134.255V30.3429H407.431V39.3035H410.138C411.835 36.4167 414.496 33.8533 418.098 31.6131C421.7 29.373 426.859 28.2529 433.575 28.2529C439.583 28.2529 445.148 29.7194 450.249 32.6524C455.362 35.5853 459.464 39.8924 462.566 45.562C465.669 51.2316 467.226 58.1021 467.226 66.1619V68.5522C467.226 76.612 465.669 83.4825 462.566 89.1521C459.464 94.8217 455.35 99.1288 450.249 102.062C445.137 104.995 439.583 106.461 433.575 106.461C429.067 106.461 425.29 105.942 422.234 104.891C419.179 103.852 416.727 102.501 414.868 100.861C413.008 99.2212 411.533 97.5584 410.441 95.861H407.733V134.232H388.805V134.255ZM427.87 90.0643C433.784 90.0643 438.665 88.1937 442.522 84.464C446.38 80.7343 448.309 75.2841 448.309 68.1134V66.6238C448.309 59.4531 446.357 54.0029 442.453 50.2732C438.548 46.5435 433.691 44.6728 427.882 44.6728C422.072 44.6728 417.215 46.5435 413.311 50.2732C409.406 54.0029 407.454 59.4531 407.454 66.6238V68.1134C407.454 75.2841 409.406 80.7343 413.311 84.464C417.215 88.1937 422.072 90.0643 427.882 90.0643H427.87Z" fill="#1C2026"/>
|
||||
<path d="M511.102 106.484C503.688 106.484 497.158 104.914 491.5 101.785C485.841 98.6439 481.437 94.2213 478.276 88.494C475.127 82.7666 473.547 76.0232 473.547 68.2635V66.4737C473.547 58.7141 475.093 51.9706 478.207 46.2433C481.309 40.5159 485.666 36.0934 491.279 32.9526C496.891 29.8233 503.398 28.2529 510.811 28.2529C518.225 28.2529 524.488 29.8695 529.891 33.1027C535.294 36.3359 539.512 40.8161 542.51 46.5435C545.519 52.2708 547.018 58.9104 547.018 66.4737V72.8939H492.778C492.975 77.9746 494.881 82.0969 498.483 85.2839C502.085 88.4709 506.5 90.0644 511.706 90.0644C516.912 90.0644 520.92 88.9212 523.419 86.6349C525.917 84.3486 527.822 81.8082 529.124 79.0254L544.601 87.0852C543.195 89.6718 541.173 92.4893 538.513 95.5262C535.852 98.563 532.331 101.15 527.915 103.286C523.512 105.422 517.899 106.496 511.09 106.496L511.102 106.484ZM492.917 58.8527H527.776C527.369 54.5687 525.65 51.1392 522.594 48.5527C519.538 45.9661 515.552 44.6729 510.649 44.6729C505.745 44.6729 501.481 45.9661 498.483 48.5527C495.473 51.1392 493.626 54.5803 492.929 58.8527H492.917Z" fill="#1C2026"/>
|
||||
<path d="M556.324 104.396V30.3442H574.95V38.7042H577.658C578.762 35.7136 580.586 33.5312 583.142 32.134C585.699 30.7368 588.673 30.0439 592.078 30.0439H601.095V46.7641H591.776C586.965 46.7641 583.014 48.0343 579.912 50.5746C576.81 53.115 575.253 57.0179 575.253 62.2949V104.396H556.324Z" fill="#1C2026"/>
|
||||
<path d="M608.299 104.395V30.3436H626.925V38.4035H629.633C630.934 35.9209 633.084 33.75 636.093 31.914C639.103 30.0781 643.053 29.1543 647.957 29.1543C653.267 29.1543 657.52 30.1704 660.727 32.2143C663.934 34.2581 666.386 36.9139 668.094 40.2048H670.801C672.498 37.0178 674.903 34.3851 678.017 32.2951C681.119 30.2051 685.523 29.1658 691.24 29.1658C695.841 29.1658 700.024 30.1358 703.789 32.0757C707.542 34.0156 710.552 36.9486 712.806 40.8861C715.06 44.8237 716.187 49.7658 716.187 55.7472V104.418H697.259V57.0866C697.259 53.0105 696.202 49.9506 694.11 47.9067C692.007 45.8629 689.044 44.8468 685.244 44.8468C680.933 44.8468 677.61 46.2209 675.251 48.9575C672.893 51.6942 671.719 55.5971 671.719 60.6778V104.43H652.791V57.0982C652.791 53.0221 651.733 49.9621 649.642 47.9183C647.539 45.8744 644.576 44.8583 640.776 44.8583C636.465 44.8583 633.142 46.2324 630.783 48.9691C628.424 51.7057 627.251 55.6086 627.251 60.6893V104.441H608.322L608.299 104.395Z" fill="#1C2026"/>
|
||||
<path d="M763.05 106.484C755.637 106.484 749.106 104.914 743.448 101.785C737.789 98.6439 733.385 94.2213 730.224 88.494C727.076 82.7666 725.495 76.0232 725.495 68.2635V66.4737C725.495 58.7141 727.041 51.9706 730.155 46.2433C733.257 40.5159 737.615 36.0934 743.227 32.9526C748.839 29.8233 755.346 28.2529 762.759 28.2529C770.173 28.2529 776.436 29.8695 781.839 33.1027C787.242 36.3359 791.46 40.8161 794.458 46.5435C797.467 52.2708 798.966 58.9104 798.966 66.4737V72.8939H744.726C744.923 77.9746 746.829 82.0969 750.431 85.2839C754.033 88.4709 758.449 90.0644 763.654 90.0644C768.86 90.0644 772.868 88.9212 775.378 86.6349C777.876 84.3486 779.782 81.8082 781.084 79.0254L796.561 87.0852C795.155 89.6718 793.133 92.4893 790.472 95.5262C787.811 98.563 784.291 101.15 779.875 103.286C775.471 105.422 769.859 106.496 763.05 106.496V106.484ZM744.877 58.8527H779.736C779.329 54.5687 777.609 51.1392 774.553 48.5527C771.497 45.9661 767.512 44.6729 762.608 44.6729C757.705 44.6729 753.44 45.9661 750.443 48.5527C747.433 51.1392 745.586 54.5803 744.888 58.8527H744.877Z" fill="#1C2026"/>
|
||||
<path d="M808.272 104.395V30.3436H826.898V38.4035H829.606C830.907 35.9209 833.057 33.75 836.066 31.914C839.076 30.0781 843.026 29.1543 847.93 29.1543C853.24 29.1543 857.493 30.1704 860.7 32.2143C863.907 34.2581 866.359 36.9139 868.067 40.2048H870.774C872.471 37.0178 874.876 34.3851 877.99 32.2951C881.092 30.2051 885.496 29.1658 891.213 29.1658C895.814 29.1658 899.997 30.1358 903.762 32.0757C907.515 34.0156 910.525 36.9486 912.779 40.8861C915.033 44.8237 916.16 49.7658 916.16 55.7472V104.418H897.232V57.0866C897.232 53.0105 896.175 49.9506 894.083 47.9067C891.98 45.8629 889.017 44.8468 885.217 44.8468C880.906 44.8468 877.583 46.2209 875.224 48.9575C872.866 51.6942 871.692 55.5971 871.692 60.6778V104.43H852.764V57.0982C852.764 53.0221 851.706 49.9621 849.615 47.9183C847.512 45.8744 844.549 44.8583 840.749 44.8583C836.438 44.8583 833.115 46.2324 830.756 48.9691C828.397 51.7057 827.224 55.6086 827.224 60.6893V104.441H808.295L808.272 104.395Z" fill="#1C2026"/>
|
||||
<path d="M964.534 106.484C957.12 106.484 950.462 104.995 944.548 102.004C938.633 99.0134 933.974 94.6832 930.569 89.0136C927.165 83.344 925.457 76.5197 925.457 68.5637V66.1735C925.457 58.206 927.153 51.3933 930.569 45.7236C933.974 40.054 938.633 35.7239 944.548 32.7332C950.451 29.7425 957.12 28.2529 964.534 28.2529C971.947 28.2529 978.605 29.7425 984.519 32.7332C990.422 35.7239 995.082 40.054 998.498 45.7236C1001.9 51.3933 1003.6 58.2176 1003.6 66.1735V68.5637C1003.6 76.5312 1001.89 83.344 998.498 89.0136C995.093 94.6832 990.434 99.0134 984.519 102.004C978.605 104.995 971.947 106.484 964.534 106.484ZM964.534 89.7642C970.343 89.7642 975.142 87.8935 978.954 84.1638C982.765 80.4341 984.659 75.0763 984.659 68.1134V66.6238C984.659 59.661 982.776 54.3031 979.023 50.5734C975.27 46.8437 970.436 44.9731 964.522 44.9731C958.608 44.9731 953.902 46.8437 950.102 50.5734C946.291 54.3031 944.397 59.661 944.397 66.6238V68.1134C944.397 75.0763 946.291 80.4341 950.102 84.1638C953.913 87.8935 958.712 89.7642 964.522 89.7642H964.534Z" fill="#1C2026"/>
|
||||
<path d="M1013.51 104.396V30.3442H1032.14V38.7042H1034.84C1035.95 35.7136 1037.77 33.5312 1040.33 32.134C1042.88 30.7368 1045.86 30.0439 1049.26 30.0439H1058.28V46.7641H1048.96C1044.15 46.7641 1040.2 48.0343 1037.1 50.5746C1034 53.115 1032.44 57.0179 1032.44 62.2949V104.396H1013.51Z" fill="#1C2026"/>
|
||||
<path d="M1073.61 134.256V117.836H1114.17C1116.97 117.836 1118.38 116.347 1118.38 113.356V94.696H1115.67C1114.87 96.3934 1113.61 98.0793 1111.92 99.7767C1110.21 101.474 1107.91 102.86 1105 103.957C1102.1 105.054 1098.39 105.596 1093.88 105.596C1088.07 105.596 1082.98 104.28 1078.64 101.636C1074.28 99.0031 1070.9 95.3426 1068.49 90.6661C1066.09 85.9895 1064.89 80.6086 1064.89 74.5464V30.3442H1083.82V73.0453C1083.82 78.6225 1085.19 82.8025 1087.96 85.5854C1090.71 88.3682 1094.64 89.7654 1099.75 89.7654C1105.56 89.7654 1110.07 87.8486 1113.27 84.015C1116.48 80.1814 1118.09 74.8351 1118.09 67.9646V30.3442H1137.01V117.536C1137.01 122.617 1135.51 126.67 1132.51 129.707C1129.5 132.744 1125.49 134.256 1120.49 134.256H1073.62H1073.61Z" fill="#1C2026"/>
|
||||
<path d="M167.067 53.1049H105.065V0H85.0325V57.6198C85.0325 63.7398 87.4842 69.6172 91.8416 73.9474L142.468 124.258L156.633 110.182L119.241 73.0236H167.079V53.1165L167.067 53.1049Z" fill="#1C2026"/>
|
||||
<path d="M10.446 24.4567L47.838 61.6152H0V81.5223H62.0023V134.627H82.0345V77.0074C82.0345 70.8875 79.5828 65.01 75.2254 60.6798L24.6103 10.3809L10.446 24.4567Z" fill="#1C2026"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 9.8 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* API service for Supermemory browser extension
|
||||
* API service for supermemory browser extension
|
||||
*/
|
||||
import { API_ENDPOINTS, STORAGE_KEYS } from "./constants"
|
||||
import {
|
||||
|
|
@ -70,47 +70,6 @@ export async function fetchProjects(): Promise<Project[]> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get projects from cache or fetch fresh
|
||||
*/
|
||||
export async function getProjects(useCache = true): Promise<Project[]> {
|
||||
if (useCache) {
|
||||
try {
|
||||
const cached = await chrome.storage.local.get([
|
||||
STORAGE_KEYS.PROJECTS_CACHE,
|
||||
])
|
||||
const cachedData = cached[STORAGE_KEYS.PROJECTS_CACHE]
|
||||
|
||||
if (cachedData?.timestamp && cachedData.projects) {
|
||||
// Cache for 5 minutes
|
||||
const cacheAge = Date.now() - cachedData.timestamp
|
||||
if (cacheAge < 5 * 60 * 1000) {
|
||||
return cachedData.projects
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("Failed to read projects cache:", error)
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch fresh data
|
||||
const projects = await fetchProjects()
|
||||
|
||||
// Cache the results
|
||||
try {
|
||||
await chrome.storage.local.set({
|
||||
[STORAGE_KEYS.PROJECTS_CACHE]: {
|
||||
projects,
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
console.warn("Failed to cache projects:", error)
|
||||
}
|
||||
|
||||
return projects
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default project from storage
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -14,29 +14,27 @@ export const API_ENDPOINTS = {
|
|||
* Storage Keys
|
||||
*/
|
||||
export const STORAGE_KEYS = {
|
||||
BEARER_TOKEN: "bearerToken",
|
||||
TWITTER_AUTH: "twitterAuth",
|
||||
TOKENS_LOGGED: "tokens_logged",
|
||||
TWITTER_COOKIE: "cookie",
|
||||
TWITTER_CSRF: "csrf",
|
||||
TWITTER_AUTH_TOKEN: "auth",
|
||||
DEFAULT_PROJECT: "defaultProject",
|
||||
PROJECTS_CACHE: "projectsCache",
|
||||
BEARER_TOKEN: "bearer-token",
|
||||
TOKENS_LOGGED: "tokens-logged",
|
||||
TWITTER_COOKIE: "twitter-cookie",
|
||||
TWITTER_CSRF: "twitter-csrf",
|
||||
TWITTER_AUTH_TOKEN: "twitter-auth-token",
|
||||
DEFAULT_PROJECT: "sm-default-project",
|
||||
} as const
|
||||
|
||||
/**
|
||||
* DOM Element IDs
|
||||
*/
|
||||
export const ELEMENT_IDS = {
|
||||
TWITTER_IMPORT_BUTTON: "supermemory-twitter-import-button",
|
||||
TWITTER_IMPORT_STATUS: "twitter-import-status",
|
||||
TWITTER_CLOSE_BTN: "twitter-close-btn",
|
||||
TWITTER_IMPORT_BTN: "twitter-import-button",
|
||||
TWITTER_SIGNIN_BTN: "twitter-signin-btn",
|
||||
SUPERMEMORY_TOAST: "supermemory-toast",
|
||||
SUPERMEMORY_SAVE_BUTTON: "supermemory-save-button",
|
||||
SAVE_TWEET_ELEMENT: "supermemory-save-tweet-element",
|
||||
CHATGPT_INPUT_BAR_ELEMENT: "supermemory-chatgpt-input-bar-element",
|
||||
TWITTER_IMPORT_BUTTON: "sm-twitter-import-button",
|
||||
TWITTER_IMPORT_STATUS: "sm-twitter-import-status",
|
||||
TWITTER_CLOSE_BTN: "sm-twitter-close-btn",
|
||||
TWITTER_IMPORT_BTN: "sm-twitter-import-btn",
|
||||
TWITTER_SIGNIN_BTN: "sm-twitter-signin-btn",
|
||||
SUPERMEMORY_TOAST: "sm-toast",
|
||||
SUPERMEMORY_SAVE_BUTTON: "sm-save-button",
|
||||
SAVE_TWEET_ELEMENT: "sm-save-tweet-element",
|
||||
CHATGPT_INPUT_BAR_ELEMENT: "sm-chatgpt-input-bar-element",
|
||||
} as const
|
||||
|
||||
/**
|
||||
|
|
@ -70,19 +68,14 @@ export const CONTAINER_TAGS = {
|
|||
* Message Types for extension communication
|
||||
*/
|
||||
export const MESSAGE_TYPES = {
|
||||
SAVE_MEMORY: "saveMemory",
|
||||
SHOW_TOAST: "showToast",
|
||||
BATCH_IMPORT_ALL: "batchImportAll",
|
||||
IMPORT_UPDATE: "import-update",
|
||||
IMPORT_DONE: "import-done",
|
||||
GET_RELATED_MEMORIES: "getRelatedMemories",
|
||||
SAVE_MEMORY: "sm-save-memory",
|
||||
SHOW_TOAST: "sm-show-toast",
|
||||
BATCH_IMPORT_ALL: "sm-batch-import-all",
|
||||
IMPORT_UPDATE: "sm-import-update",
|
||||
IMPORT_DONE: "sm-import-done",
|
||||
GET_RELATED_MEMORIES: "sm-get-related-memories",
|
||||
} as const
|
||||
|
||||
export const CONTEXT_MENU_IDS = {
|
||||
SAVE_TO_SUPERMEMORY: "save-to-supermemory",
|
||||
} as const
|
||||
|
||||
export const CSS_CLASSES = {
|
||||
TOAST_STYLES_ID: "supermemory-toast-styles",
|
||||
SPINNER_STYLES_ID: "supermemory-spinner-styles",
|
||||
SAVE_TO_SUPERMEMORY: "sm-save-to-supermemory",
|
||||
} as const
|
||||
|
|
|
|||
24
apps/browser-extension/utils/query-client.ts
Normal file
24
apps/browser-extension/utils/query-client.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* React Query configuration for supermemory browser extension
|
||||
*/
|
||||
import { QueryClient } from "@tanstack/react-query"
|
||||
|
||||
export const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
gcTime: 10 * 60 * 1000, // 10 minutes (previously cacheTime)
|
||||
retry: (failureCount, error) => {
|
||||
// Don't retry on authentication errors
|
||||
if (error?.constructor?.name === "AuthenticationError") {
|
||||
return false
|
||||
}
|
||||
return failureCount < 3
|
||||
},
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
mutations: {
|
||||
retry: 1,
|
||||
},
|
||||
},
|
||||
})
|
||||
64
apps/browser-extension/utils/query-hooks.ts
Normal file
64
apps/browser-extension/utils/query-hooks.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* React Query hooks for supermemory API
|
||||
*/
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
||||
import {
|
||||
fetchProjects,
|
||||
getDefaultProject,
|
||||
saveMemory,
|
||||
searchMemories,
|
||||
setDefaultProject,
|
||||
} from "./api"
|
||||
import type { MemoryPayload } from "./types"
|
||||
|
||||
// Query Keys
|
||||
export const queryKeys = {
|
||||
projects: ["projects"] as const,
|
||||
defaultProject: ["defaultProject"] as const,
|
||||
}
|
||||
|
||||
// Projects Query
|
||||
export function useProjects(options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: queryKeys.projects,
|
||||
queryFn: fetchProjects,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
enabled: options?.enabled ?? true,
|
||||
})
|
||||
}
|
||||
|
||||
// Default Project Query
|
||||
export function useDefaultProject(options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: queryKeys.defaultProject,
|
||||
queryFn: getDefaultProject,
|
||||
staleTime: 2 * 60 * 1000, // 2 minutes
|
||||
enabled: options?.enabled ?? true,
|
||||
})
|
||||
}
|
||||
|
||||
// Set Default Project Mutation
|
||||
export function useSetDefaultProject() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: setDefaultProject,
|
||||
onSuccess: (_, project) => {
|
||||
queryClient.setQueryData(queryKeys.defaultProject, project)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Save Memory Mutation
|
||||
export function useSaveMemory() {
|
||||
return useMutation({
|
||||
mutationFn: (payload: MemoryPayload) => saveMemory(payload),
|
||||
})
|
||||
}
|
||||
|
||||
// Search Memories Mutation
|
||||
export function useSearchMemories() {
|
||||
return useMutation({
|
||||
mutationFn: (query: string) => searchMemories(query),
|
||||
})
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
* Twitter Authentication Module
|
||||
* Handles token capture and storage for Twitter API access
|
||||
*/
|
||||
import { STORAGE_KEYS } from "./constants"
|
||||
|
||||
export interface TwitterAuthTokens {
|
||||
cookie: string
|
||||
|
|
@ -34,17 +35,17 @@ export function captureTwitterTokens(
|
|||
)
|
||||
|
||||
if (authHeader?.value && cookieHeader?.value && csrfHeader?.value) {
|
||||
chrome.storage.session.get(["tokens_logged"], (result) => {
|
||||
if (!result.tokens_logged) {
|
||||
chrome.storage.session.get([STORAGE_KEYS.TOKENS_LOGGED], (result) => {
|
||||
if (!result[STORAGE_KEYS.TOKENS_LOGGED]) {
|
||||
console.log("Twitter auth tokens captured successfully")
|
||||
chrome.storage.session.set({ tokens_logged: true })
|
||||
chrome.storage.session.set({ [STORAGE_KEYS.TOKENS_LOGGED]: true })
|
||||
}
|
||||
})
|
||||
|
||||
chrome.storage.session.set({
|
||||
cookie: cookieHeader.value,
|
||||
csrf: csrfHeader.value,
|
||||
auth: authHeader.value,
|
||||
[STORAGE_KEYS.TWITTER_COOKIE]: cookieHeader.value,
|
||||
[STORAGE_KEYS.TWITTER_CSRF]: csrfHeader.value,
|
||||
[STORAGE_KEYS.TWITTER_AUTH_TOKEN]: authHeader.value,
|
||||
})
|
||||
|
||||
return true
|
||||
|
|
@ -58,16 +59,24 @@ export function captureTwitterTokens(
|
|||
* @returns Promise resolving to tokens or null if not available
|
||||
*/
|
||||
export async function getTwitterTokens(): Promise<TwitterAuthTokens | null> {
|
||||
const result = await chrome.storage.session.get(["cookie", "csrf", "auth"])
|
||||
const result = await chrome.storage.session.get([
|
||||
STORAGE_KEYS.TWITTER_COOKIE,
|
||||
STORAGE_KEYS.TWITTER_CSRF,
|
||||
STORAGE_KEYS.TWITTER_AUTH_TOKEN,
|
||||
])
|
||||
|
||||
if (!result.cookie || !result.csrf || !result.auth) {
|
||||
if (
|
||||
!result[STORAGE_KEYS.TWITTER_COOKIE] ||
|
||||
!result[STORAGE_KEYS.TWITTER_CSRF] ||
|
||||
!result[STORAGE_KEYS.TWITTER_AUTH_TOKEN]
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
cookie: result.cookie,
|
||||
csrf: result.csrf,
|
||||
auth: result.auth,
|
||||
cookie: result[STORAGE_KEYS.TWITTER_COOKIE],
|
||||
csrf: result[STORAGE_KEYS.TWITTER_CSRF],
|
||||
auth: result[STORAGE_KEYS.TWITTER_AUTH_TOKEN],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ export function createTwitterImportButton(onClick: () => void): HTMLElement {
|
|||
transition: all 0.2s ease;
|
||||
`
|
||||
|
||||
const iconUrl = browser.runtime.getURL("/light-mode-icon.png")
|
||||
const iconUrl = browser.runtime.getURL("/icon-16.png")
|
||||
button.innerHTML = `
|
||||
<img src="${iconUrl}" width="20" height="20" alt="Save to Memory" style="border-radius: 4px;" />
|
||||
`
|
||||
|
|
|
|||
|
|
@ -24,10 +24,7 @@ export default defineConfig({
|
|||
],
|
||||
web_accessible_resources: [
|
||||
{
|
||||
resources: [
|
||||
"icon-16.png",
|
||||
"fonts/*.ttf",
|
||||
],
|
||||
resources: ["icon-16.png", "fonts/*.ttf"],
|
||||
matches: ["<all_urls>"],
|
||||
},
|
||||
],
|
||||
|
|
|
|||
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
Loading…
Add table
Reference in a new issue