mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
chore: remove unused modules
Three modules have no remaining references anywhere in the repo (verified by grep across all tracked source, excluding generated WXT type stubs): - `packages/lib/glass-effect-manager.ts` - a WebGL glass-effect singleton; nothing imports it, and the live glass UI (`packages/ui/other/glass-effect.tsx`) does not use it. - `useDeleteDocument` in `packages/lib/queries.ts` - an unused delete-document mutation hook. Its removal also drops the now-unused react-query, sonner, zod and $fetch imports from that file; the subscription-status helpers that remain are pure and need none of them. - `apps/browser-extension/utils/memory-popup.ts` - a memory popup helper only referenced by auto-generated WXT import stubs, never by a content script. Removing dead weight. Happy to keep any of these if they are planned for upcoming work.
This commit is contained in:
parent
5ecbc26345
commit
43bab43d16
3 changed files with 0 additions and 498 deletions
|
|
@ -1,93 +0,0 @@
|
|||
/**
|
||||
* Memory Popup Utilities
|
||||
* Standardized popup positioning and styling for memory display across platforms
|
||||
*/
|
||||
|
||||
export interface MemoryPopupConfig {
|
||||
memoriesData: string
|
||||
onClose: () => void
|
||||
onRemove?: () => void
|
||||
}
|
||||
|
||||
export function createMemoryPopup(config: MemoryPopupConfig): HTMLElement {
|
||||
const popup = document.createElement("div")
|
||||
popup.style.cssText = `
|
||||
position: fixed;
|
||||
bottom: 80px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: #1a1a1a;
|
||||
color: white;
|
||||
padding: 0;
|
||||
border-radius: 12px;
|
||||
font-size: 13px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
|
||||
max-width: 500px;
|
||||
max-height: 400px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
||||
z-index: 999999;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
`
|
||||
|
||||
const header = document.createElement("div")
|
||||
header.style.cssText = `
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid #333;
|
||||
opacity: 0.8;
|
||||
`
|
||||
header.innerHTML = `
|
||||
<span style="font-size: 11px; font-weight: 600; letter-spacing: 0.5px;">INCLUDED MEMORIES</span>
|
||||
<div style="display: flex; gap: 4px;">
|
||||
${config.onRemove ? '<button id="remove-memories-btn" style="background: none; border: none; color: #ff4444; cursor: pointer; font-size: 14px; padding: 2px; border-radius: 2px;" title="Remove memories">✕</button>' : ""}
|
||||
<button id="close-popup-btn" style="background: none; border: none; color: white; cursor: pointer; font-size: 14px; padding: 2px; border-radius: 2px;">✕</button>
|
||||
</div>
|
||||
`
|
||||
|
||||
const content = document.createElement("div")
|
||||
content.style.cssText = `
|
||||
padding: 8px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
line-height: 1.4;
|
||||
`
|
||||
content.textContent = config.memoriesData
|
||||
|
||||
const closeBtn = header.querySelector("#close-popup-btn")
|
||||
closeBtn?.addEventListener("click", config.onClose)
|
||||
|
||||
const removeBtn = header.querySelector("#remove-memories-btn")
|
||||
if (removeBtn && config.onRemove) {
|
||||
removeBtn.addEventListener("click", config.onRemove)
|
||||
}
|
||||
|
||||
popup.appendChild(header)
|
||||
popup.appendChild(content)
|
||||
|
||||
return popup
|
||||
}
|
||||
|
||||
export function showMemoryPopup(popup: HTMLElement): void {
|
||||
popup.style.display = "block"
|
||||
|
||||
setTimeout(() => {
|
||||
if (popup.style.display === "block") {
|
||||
hideMemoryPopup(popup)
|
||||
}
|
||||
}, 10000)
|
||||
}
|
||||
|
||||
export function hideMemoryPopup(popup: HTMLElement): void {
|
||||
popup.style.display = "none"
|
||||
}
|
||||
|
||||
export function toggleMemoryPopup(popup: HTMLElement): void {
|
||||
if (popup.style.display === "none" || popup.style.display === "") {
|
||||
showMemoryPopup(popup)
|
||||
} else {
|
||||
hideMemoryPopup(popup)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,308 +0,0 @@
|
|||
// Singleton WebGL context manager for glass effects
|
||||
class GlassEffectManager {
|
||||
private static instance: GlassEffectManager | null = null
|
||||
private canvas: HTMLCanvasElement | null = null
|
||||
private gl: WebGLRenderingContext | null = null
|
||||
private program: WebGLProgram | null = null
|
||||
private uniforms: Record<string, WebGLUniformLocation | null> = {}
|
||||
private effects: Map<string, EffectInstance> = new Map()
|
||||
private animationFrame: number | null = null
|
||||
private startTime: number = performance.now()
|
||||
private mousePositions: Map<string, { x: number; y: number }> = new Map()
|
||||
|
||||
static getInstance(): GlassEffectManager {
|
||||
if (!GlassEffectManager.instance) {
|
||||
GlassEffectManager.instance = new GlassEffectManager()
|
||||
}
|
||||
return GlassEffectManager.instance
|
||||
}
|
||||
|
||||
private constructor() {
|
||||
this.initializeContext()
|
||||
}
|
||||
|
||||
private initializeContext() {
|
||||
// Create offscreen canvas
|
||||
this.canvas = document.createElement("canvas")
|
||||
this.canvas.width = 1024 // Default size, will be adjusted
|
||||
this.canvas.height = 1024
|
||||
|
||||
this.gl = this.canvas.getContext("webgl", {
|
||||
alpha: true,
|
||||
premultipliedAlpha: false,
|
||||
preserveDrawingBuffer: true,
|
||||
})
|
||||
|
||||
if (!this.gl) {
|
||||
console.error("WebGL not supported")
|
||||
return
|
||||
}
|
||||
|
||||
this.setupShaders()
|
||||
this.startRenderLoop()
|
||||
}
|
||||
|
||||
private setupShaders() {
|
||||
if (!this.gl) return
|
||||
|
||||
const vsSource = `
|
||||
attribute vec2 position;
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`
|
||||
|
||||
const fsSource = `
|
||||
precision mediump float;
|
||||
|
||||
uniform vec2 iResolution;
|
||||
uniform float iTime;
|
||||
uniform vec2 iMouse;
|
||||
uniform float iExpanded;
|
||||
|
||||
float noise(vec2 p) {
|
||||
return sin(p.x * 10.0) * sin(p.y * 10.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = gl_FragCoord.xy / iResolution.xy;
|
||||
vec2 mouse = iMouse / iResolution.xy;
|
||||
|
||||
float dist = length(uv - mouse);
|
||||
|
||||
vec2 distortion = vec2(
|
||||
sin(iTime * 2.0 + uv.y * 10.0) * 0.0025,
|
||||
cos(iTime * 1.5 + uv.x * 10.0) * 0.0025
|
||||
);
|
||||
|
||||
vec2 refractedUV = uv + distortion * (1.0 - dist);
|
||||
|
||||
vec3 glassColor = mix(
|
||||
vec3(0.1, 0.1, 0.12),
|
||||
vec3(0.16, 0.16, 0.19),
|
||||
1.0 - length(uv - vec2(0.5))
|
||||
);
|
||||
|
||||
float glow = exp(-dist * 5.0) * 0.35;
|
||||
glassColor += vec3(glow);
|
||||
|
||||
float edge = 1.0 - smoothstep(0.0, 0.02, min(
|
||||
min(uv.x, 1.0 - uv.x),
|
||||
min(uv.y, 1.0 - uv.y)
|
||||
));
|
||||
glassColor += edge * 0.3;
|
||||
|
||||
float edgeGlow = 1.0 - smoothstep(0.0, 0.05, min(
|
||||
min(uv.x, 1.0 - uv.x),
|
||||
min(uv.y, 1.0 - uv.y)
|
||||
));
|
||||
glassColor += vec3(edgeGlow * 0.1, edgeGlow * 0.1, edgeGlow * 0.2);
|
||||
|
||||
float n = noise(refractedUV * 50.0 + vec2(iTime)) * 0.025;
|
||||
glassColor += vec3(n);
|
||||
|
||||
float alpha = 0.25 + edge * 0.2 + glow * 0.2;
|
||||
alpha *= mix(0.8, 1.0, iExpanded);
|
||||
|
||||
gl_FragColor = vec4(glassColor, alpha);
|
||||
}
|
||||
`
|
||||
|
||||
const createShader = (type: number, source: string) => {
|
||||
const shader = this.gl!.createShader(type)
|
||||
if (!shader) return null
|
||||
|
||||
this.gl!.shaderSource(shader, source)
|
||||
this.gl!.compileShader(shader)
|
||||
|
||||
if (!this.gl!.getShaderParameter(shader, this.gl!.COMPILE_STATUS)) {
|
||||
console.error("Shader error:", this.gl!.getShaderInfoLog(shader))
|
||||
this.gl!.deleteShader(shader)
|
||||
return null
|
||||
}
|
||||
return shader
|
||||
}
|
||||
|
||||
const vs = createShader(this.gl.VERTEX_SHADER, vsSource)
|
||||
const fs = createShader(this.gl.FRAGMENT_SHADER, fsSource)
|
||||
if (!vs || !fs) return
|
||||
|
||||
this.program = this.gl.createProgram()
|
||||
if (!this.program) return
|
||||
|
||||
this.gl.attachShader(this.program, vs)
|
||||
this.gl.attachShader(this.program, fs)
|
||||
this.gl.linkProgram(this.program)
|
||||
// biome-ignore lint/correctness/useHookAtTopLevel: Well, not a hook
|
||||
this.gl.useProgram(this.program)
|
||||
|
||||
// Buffer setup
|
||||
const buffer = this.gl.createBuffer()
|
||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer)
|
||||
this.gl.bufferData(
|
||||
this.gl.ARRAY_BUFFER,
|
||||
new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),
|
||||
this.gl.STATIC_DRAW,
|
||||
)
|
||||
|
||||
const position = this.gl.getAttribLocation(this.program, "position")
|
||||
this.gl.enableVertexAttribArray(position)
|
||||
this.gl.vertexAttribPointer(position, 2, this.gl.FLOAT, false, 0, 0)
|
||||
|
||||
// Store uniform locations
|
||||
this.uniforms = {
|
||||
resolution: this.gl.getUniformLocation(this.program, "iResolution"),
|
||||
time: this.gl.getUniformLocation(this.program, "iTime"),
|
||||
mouse: this.gl.getUniformLocation(this.program, "iMouse"),
|
||||
expanded: this.gl.getUniformLocation(this.program, "iExpanded"),
|
||||
}
|
||||
|
||||
// Enable blending
|
||||
this.gl.enable(this.gl.BLEND)
|
||||
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA)
|
||||
}
|
||||
|
||||
registerEffect(
|
||||
id: string,
|
||||
targetCanvas: HTMLCanvasElement,
|
||||
isExpanded: boolean,
|
||||
): () => void {
|
||||
// Ensure minimum dimensions
|
||||
const width = Math.max(1, targetCanvas.width)
|
||||
const height = Math.max(1, targetCanvas.height)
|
||||
|
||||
const effect: EffectInstance = {
|
||||
id,
|
||||
targetCanvas,
|
||||
isExpanded,
|
||||
width,
|
||||
height,
|
||||
}
|
||||
|
||||
this.effects.set(id, effect)
|
||||
this.mousePositions.set(id, { x: 0, y: 0 })
|
||||
|
||||
// Return cleanup function
|
||||
return () => {
|
||||
this.effects.delete(id)
|
||||
this.mousePositions.delete(id)
|
||||
if (this.effects.size === 0 && this.animationFrame) {
|
||||
cancelAnimationFrame(this.animationFrame)
|
||||
this.animationFrame = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateMousePosition(id: string, x: number, y: number) {
|
||||
this.mousePositions.set(id, { x, y })
|
||||
}
|
||||
|
||||
updateExpanded(id: string, isExpanded: boolean) {
|
||||
const effect = this.effects.get(id)
|
||||
if (effect) {
|
||||
effect.isExpanded = isExpanded
|
||||
}
|
||||
}
|
||||
|
||||
updateSize(id: string, width: number, height: number) {
|
||||
const effect = this.effects.get(id)
|
||||
if (effect) {
|
||||
// Ensure minimum dimensions
|
||||
effect.width = Math.max(1, width)
|
||||
effect.height = Math.max(1, height)
|
||||
}
|
||||
}
|
||||
|
||||
private startRenderLoop() {
|
||||
const render = () => {
|
||||
if (!this.gl || !this.program || this.effects.size === 0) {
|
||||
this.animationFrame = requestAnimationFrame(render)
|
||||
return
|
||||
}
|
||||
|
||||
const currentTime = (performance.now() - this.startTime) / 1000
|
||||
|
||||
// Render each effect
|
||||
for (const [id, effect] of Array.from(this.effects)) {
|
||||
const mousePos = this.mousePositions.get(id) || { x: 0, y: 0 }
|
||||
|
||||
// Skip rendering if dimensions are invalid
|
||||
if (effect.width <= 0 || effect.height <= 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Set canvas size if needed
|
||||
if (
|
||||
this.canvas!.width !== effect.width ||
|
||||
this.canvas!.height !== effect.height
|
||||
) {
|
||||
this.canvas!.width = effect.width
|
||||
this.canvas!.height = effect.height
|
||||
this.gl.viewport(0, 0, effect.width, effect.height)
|
||||
}
|
||||
|
||||
// Clear and render
|
||||
this.gl.clearColor(0, 0, 0, 0)
|
||||
this.gl.clear(this.gl.COLOR_BUFFER_BIT)
|
||||
|
||||
// Set uniforms
|
||||
if (this.uniforms.resolution) {
|
||||
this.gl.uniform2f(
|
||||
this.uniforms.resolution,
|
||||
effect.width,
|
||||
effect.height,
|
||||
)
|
||||
}
|
||||
if (this.uniforms.time) {
|
||||
this.gl.uniform1f(this.uniforms.time, currentTime)
|
||||
}
|
||||
if (this.uniforms.mouse) {
|
||||
this.gl.uniform2f(this.uniforms.mouse, mousePos.x, mousePos.y)
|
||||
}
|
||||
if (this.uniforms.expanded) {
|
||||
this.gl.uniform1f(
|
||||
this.uniforms.expanded,
|
||||
effect.isExpanded ? 1.0 : 0.0,
|
||||
)
|
||||
}
|
||||
|
||||
// Draw
|
||||
this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4)
|
||||
|
||||
// Copy to target canvas
|
||||
const targetCtx = effect.targetCanvas.getContext("2d")
|
||||
if (targetCtx) {
|
||||
targetCtx.clearRect(0, 0, effect.width, effect.height)
|
||||
targetCtx.drawImage(this.canvas!, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
this.animationFrame = requestAnimationFrame(render)
|
||||
}
|
||||
|
||||
render()
|
||||
}
|
||||
|
||||
// Clean up method (optional, for when the app unmounts)
|
||||
destroy() {
|
||||
if (this.animationFrame) {
|
||||
cancelAnimationFrame(this.animationFrame)
|
||||
}
|
||||
if (this.gl && this.program) {
|
||||
this.gl.deleteProgram(this.program)
|
||||
}
|
||||
this.effects.clear()
|
||||
this.mousePositions.clear()
|
||||
GlassEffectManager.instance = null
|
||||
}
|
||||
}
|
||||
|
||||
interface EffectInstance {
|
||||
id: string
|
||||
targetCanvas: HTMLCanvasElement
|
||||
isExpanded: boolean
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export default GlassEffectManager
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
import { useMutation, useQueryClient } from "@tanstack/react-query"
|
||||
import { toast } from "sonner"
|
||||
import type { z } from "zod"
|
||||
import type { DocumentsWithMemoriesResponseSchema } from "../validation/api"
|
||||
import { $fetch } from "./api"
|
||||
|
||||
type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema>
|
||||
type DocumentWithMemories = DocumentsResponse["documents"][0]
|
||||
|
||||
export const PLAN_TIERS = [
|
||||
"api_pro",
|
||||
"api_max",
|
||||
|
|
@ -93,91 +84,3 @@ export function getCanceledSubscription(
|
|||
endsAt: sub.currentPeriodEnd ?? sub.expiresAt ?? null,
|
||||
}
|
||||
}
|
||||
|
||||
export const useDeleteDocument = (selectedProject: string) => {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (documentId: string) => {
|
||||
// context for LLM: delete/memories/:documentId is documents delete endpoint not memories delete endpoint
|
||||
const response = await $fetch(`@delete/documents/${documentId}`)
|
||||
if (response.error) {
|
||||
throw new Error(response.error?.message || "Failed to delete document")
|
||||
}
|
||||
return response.data
|
||||
},
|
||||
onMutate: async (documentId: string) => {
|
||||
await queryClient.cancelQueries({
|
||||
queryKey: ["documents-with-memories", selectedProject],
|
||||
})
|
||||
|
||||
const previousData = queryClient.getQueryData([
|
||||
"documents-with-memories",
|
||||
selectedProject,
|
||||
])
|
||||
|
||||
queryClient.setQueryData(
|
||||
["documents-with-memories", selectedProject],
|
||||
(old: unknown) => {
|
||||
if (!old || typeof old !== "object") return old
|
||||
|
||||
// Handle Infinite Query structure (TanStack Query v5 uses 'pages')
|
||||
if (
|
||||
"pages" in old &&
|
||||
Array.isArray((old as Record<string, unknown>).pages)
|
||||
) {
|
||||
const typedOld = old as {
|
||||
pages: Array<{ documents?: DocumentWithMemories[] }>
|
||||
}
|
||||
return {
|
||||
...typedOld,
|
||||
pages: typedOld.pages.map((page) => ({
|
||||
...page,
|
||||
documents: page.documents?.filter(
|
||||
(doc: DocumentWithMemories) => doc.id !== documentId,
|
||||
),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Standard Query structure
|
||||
if (
|
||||
"documents" in old &&
|
||||
Array.isArray((old as Record<string, unknown>).documents)
|
||||
) {
|
||||
const typedOld = old as { documents: DocumentWithMemories[] }
|
||||
return {
|
||||
...typedOld,
|
||||
documents: typedOld.documents.filter(
|
||||
(doc: DocumentWithMemories) => doc.id !== documentId,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
return old
|
||||
},
|
||||
)
|
||||
|
||||
return { previousData }
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success("Memory deleted successfully")
|
||||
},
|
||||
onError: (error, _documentId, context) => {
|
||||
if (context?.previousData) {
|
||||
queryClient.setQueryData(
|
||||
["documents-with-memories", selectedProject],
|
||||
context.previousData,
|
||||
)
|
||||
}
|
||||
toast.error("Failed to delete memory", {
|
||||
description: error instanceof Error ? error.message : "Unknown error",
|
||||
})
|
||||
},
|
||||
onSettled: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["documents-with-memories", selectedProject],
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue