supermemory/apps/browser-extension/utils/route-detection.ts
MaheshtheDev d7cc7d847d feat (extension) : Auto Search Toggle for Chat Applications (#418)
Adds user-controlled auto search functionality for memories across ChatGPT, Claude, and T3.chat with a settings toggle in the extension popup.

  Changes

  - Settings UI: Added new "Settings" tab in popup with toggle to enable/disable auto search
  - Auto Search: Automatically searches user memories while typing in chat apps (disabled by default)
  - Chat Integration: Supports ChatGPT, Claude, and T3.chat with consistent behavior
  - User Control: Users can enable/disable auto search via Settings tab
  - Storage: Added AUTO_SEARCH_ENABLED storage key with default value false

  Features

  -  Auto search memories while typing (when enabled)
  -  Manual search always available via supermemory icons
  -  Works across all supported chat platforms
  -  Real-time toggle without requiring page refresh
2025-09-10 03:55:53 +00:00

117 lines
2.9 KiB
TypeScript

/**
* Route Detection Utilities
* Shared logic for detecting route changes across different AI chat platforms
*/
import { UI_CONFIG } from "./constants"
export interface RouteDetectionConfig {
platform: string
selectors: string[]
reinitCallback: () => void
checkInterval?: number
observerThrottleDelay?: number
}
export interface RouteDetectionCleanup {
observer: MutationObserver | null
urlCheckInterval: NodeJS.Timeout | null
observerThrottle: NodeJS.Timeout | null
}
export function createRouteDetection(
config: RouteDetectionConfig,
cleanup: RouteDetectionCleanup,
): void {
if (cleanup.observer) {
cleanup.observer.disconnect()
}
if (cleanup.urlCheckInterval) {
clearInterval(cleanup.urlCheckInterval)
}
if (cleanup.observerThrottle) {
clearTimeout(cleanup.observerThrottle)
cleanup.observerThrottle = null
}
let currentUrl = window.location.href
const checkForRouteChange = () => {
if (window.location.href !== currentUrl) {
currentUrl = window.location.href
console.log(`${config.platform} route changed, re-initializing`)
setTimeout(config.reinitCallback, 1000)
}
}
cleanup.urlCheckInterval = setInterval(
checkForRouteChange,
config.checkInterval || UI_CONFIG.ROUTE_CHECK_INTERVAL,
)
cleanup.observer = new MutationObserver((mutations) => {
if (cleanup.observerThrottle) {
return
}
let shouldRecheck = false
mutations.forEach((mutation) => {
if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
const element = node as Element
for (const selector of config.selectors) {
if (
element.querySelector?.(selector) ||
element.matches?.(selector)
) {
shouldRecheck = true
break
}
}
}
})
}
})
if (shouldRecheck) {
cleanup.observerThrottle = setTimeout(() => {
try {
cleanup.observerThrottle = null
config.reinitCallback()
} catch (error) {
console.error(`Error in ${config.platform} observer callback:`, error)
}
}, config.observerThrottleDelay || UI_CONFIG.OBSERVER_THROTTLE_DELAY)
}
})
try {
cleanup.observer.observe(document.body, {
childList: true,
subtree: true,
})
} catch (error) {
console.error(`Failed to set up ${config.platform} route observer:`, error)
if (cleanup.urlCheckInterval) {
clearInterval(cleanup.urlCheckInterval)
}
cleanup.urlCheckInterval = setInterval(checkForRouteChange, 1000)
}
}
export function cleanupRouteDetection(cleanup: RouteDetectionCleanup): void {
if (cleanup.observer) {
cleanup.observer.disconnect()
cleanup.observer = null
}
if (cleanup.urlCheckInterval) {
clearInterval(cleanup.urlCheckInterval)
cleanup.urlCheckInterval = null
}
if (cleanup.observerThrottle) {
clearTimeout(cleanup.observerThrottle)
cleanup.observerThrottle = null
}
}