mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-20 05:54:01 +00:00
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
116 lines
2.8 KiB
TypeScript
116 lines
2.8 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
|
|
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
|
|
}
|
|
}
|