diff --git a/apps/web/app/global-error.tsx b/apps/web/app/global-error.tsx index 9bda5fee..e586eac7 100644 --- a/apps/web/app/global-error.tsx +++ b/apps/web/app/global-error.tsx @@ -1,23 +1,27 @@ -"use client"; +"use client" -import * as Sentry from "@sentry/nextjs"; -import NextError from "next/error"; -import { useEffect } from "react"; +import * as Sentry from "@sentry/nextjs" +import NextError from "next/error" +import { useEffect } from "react" -export default function GlobalError({ error }: { error: Error & { digest?: string } }) { - useEffect(() => { - Sentry.captureException(error); - }, [error]); +export default function GlobalError({ + error, +}: { + error: Error & { digest?: string } +}) { + useEffect(() => { + Sentry.captureException(error) + }, [error]) - return ( - - - {/* `NextError` is the default Next.js error page component. Its type + return ( + + + {/* `NextError` is the default Next.js error page component. Its type definition requires a `statusCode` prop. However, since the App Router does not expose status codes for errors, we simply pass 0 to render a generic error message. */} - - - - ); -} \ No newline at end of file + + + + ) +} diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index 622eb2c1..707e4185 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -33,7 +33,10 @@ export default function RootLayout({ }>) { return ( - + + Memory Graph
void; - onAnimationStart?: () => void; - segmentWrapperClassName?: string; - containerTransition?: Transition; - segmentTransition?: Transition; - style?: React.CSSProperties; -}; + children: string + per?: PerType + as?: keyof React.JSX.IntrinsicElements + variants?: { + container?: Variants + item?: Variants + } + className?: string + preset?: PresetType + delay?: number + speedReveal?: number + speedSegment?: number + trigger?: boolean + onAnimationComplete?: () => void + onAnimationStart?: () => void + segmentWrapperClassName?: string + containerTransition?: Transition + segmentTransition?: Transition + style?: React.CSSProperties +} const defaultStaggerTimes: Record = { - char: 0.03, - word: 0.05, - line: 0.1, -}; + char: 0.03, + word: 0.05, + line: 0.1, +} const defaultContainerVariants: Variants = { - hidden: { opacity: 0 }, - visible: { - opacity: 1, - transition: { - staggerChildren: 0.05, - }, - }, - exit: { - transition: { staggerChildren: 0.05, staggerDirection: -1 }, - }, -}; + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.05, + }, + }, + exit: { + transition: { staggerChildren: 0.05, staggerDirection: -1 }, + }, +} const defaultItemVariants: Variants = { - hidden: { opacity: 0 }, - visible: { - opacity: 1, - }, - exit: { opacity: 0 }, -}; + hidden: { opacity: 0 }, + visible: { + opacity: 1, + }, + exit: { opacity: 0 }, +} const presetVariants: Record< - PresetType, - { container: Variants; item: Variants } + PresetType, + { container: Variants; item: Variants } > = { - blur: { - container: defaultContainerVariants, - item: { - hidden: { opacity: 0, filter: 'blur(12px)' }, - visible: { opacity: 1, filter: 'blur(0px)' }, - exit: { opacity: 0, filter: 'blur(12px)' }, - }, - }, - 'fade-in-blur': { - container: defaultContainerVariants, - item: { - hidden: { opacity: 0, y: 20, filter: 'blur(12px)' }, - visible: { opacity: 1, y: 0, filter: 'blur(0px)' }, - exit: { opacity: 0, y: 20, filter: 'blur(12px)' }, - }, - }, - scale: { - container: defaultContainerVariants, - item: { - hidden: { opacity: 0, scale: 0 }, - visible: { opacity: 1, scale: 1 }, - exit: { opacity: 0, scale: 0 }, - }, - }, - fade: { - container: defaultContainerVariants, - item: { - hidden: { opacity: 0 }, - visible: { opacity: 1 }, - exit: { opacity: 0 }, - }, - }, - slide: { - container: defaultContainerVariants, - item: { - hidden: { opacity: 0, y: 20 }, - visible: { opacity: 1, y: 0 }, - exit: { opacity: 0, y: 20 }, - }, - }, -}; + blur: { + container: defaultContainerVariants, + item: { + hidden: { opacity: 0, filter: "blur(12px)" }, + visible: { opacity: 1, filter: "blur(0px)" }, + exit: { opacity: 0, filter: "blur(12px)" }, + }, + }, + "fade-in-blur": { + container: defaultContainerVariants, + item: { + hidden: { opacity: 0, y: 20, filter: "blur(12px)" }, + visible: { opacity: 1, y: 0, filter: "blur(0px)" }, + exit: { opacity: 0, y: 20, filter: "blur(12px)" }, + }, + }, + scale: { + container: defaultContainerVariants, + item: { + hidden: { opacity: 0, scale: 0 }, + visible: { opacity: 1, scale: 1 }, + exit: { opacity: 0, scale: 0 }, + }, + }, + fade: { + container: defaultContainerVariants, + item: { + hidden: { opacity: 0 }, + visible: { opacity: 1 }, + exit: { opacity: 0 }, + }, + }, + slide: { + container: defaultContainerVariants, + item: { + hidden: { opacity: 0, y: 20 }, + visible: { opacity: 1, y: 0 }, + exit: { opacity: 0, y: 20 }, + }, + }, +} const AnimationComponent: React.FC<{ - segment: string; - variants: Variants; - per: 'line' | 'word' | 'char'; - segmentWrapperClassName?: string; + segment: string + variants: Variants + per: "line" | "word" | "char" + segmentWrapperClassName?: string }> = React.memo(({ segment, variants, per, segmentWrapperClassName }) => { - const content = - per === 'line' ? ( - - {segment} - - ) : per === 'word' ? ( - - ) : ( - - {segment.split('').map((char, charIndex) => ( - - ))} - - ); + const content = + per === "line" ? ( + + {segment} + + ) : per === "word" ? ( + + ) : ( + + {segment.split("").map((char, charIndex) => ( + + ))} + + ) - if (!segmentWrapperClassName) { - return content; - } + if (!segmentWrapperClassName) { + return content + } - const defaultWrapperClassName = per === 'line' ? 'block' : 'inline-block'; + const defaultWrapperClassName = per === "line" ? "block" : "inline-block" - return ( - - {content} - - ); -}); + return ( + + {content} + + ) +}) -AnimationComponent.displayName = 'AnimationComponent'; +AnimationComponent.displayName = "AnimationComponent" const splitText = (text: string, per: PerType) => { - if (per === 'line') return text.split('\n'); - return text.split(/(\s+)/); -}; + if (per === "line") return text.split("\n") + return text.split(/(\s+)/) +} const hasTransition = ( - variant?: Variant + variant?: Variant, ): variant is TargetAndTransition & { transition?: Transition } => { - if (!variant) return false; - return ( - typeof variant === 'object' && 'transition' in variant - ); -}; + if (!variant) return false + return typeof variant === "object" && "transition" in variant +} const createVariantsWithTransition = ( - baseVariants: Variants, - transition?: Transition & { exit?: Transition } + baseVariants: Variants, + transition?: Transition & { exit?: Transition }, ): Variants => { - if (!transition) return baseVariants; + if (!transition) return baseVariants - const { exit: _, ...mainTransition } = transition; + const { exit: _, ...mainTransition } = transition - return { - ...baseVariants, - visible: { - ...baseVariants.visible, - transition: { - ...(hasTransition(baseVariants.visible) - ? baseVariants.visible.transition - : {}), - ...mainTransition, - }, - }, - exit: { - ...baseVariants.exit, - transition: { - ...(hasTransition(baseVariants.exit) - ? baseVariants.exit.transition - : {}), - ...mainTransition, - staggerDirection: -1, - }, - }, - }; -}; + return { + ...baseVariants, + visible: { + ...baseVariants.visible, + transition: { + ...(hasTransition(baseVariants.visible) + ? baseVariants.visible.transition + : {}), + ...mainTransition, + }, + }, + exit: { + ...baseVariants.exit, + transition: { + ...(hasTransition(baseVariants.exit) + ? baseVariants.exit.transition + : {}), + ...mainTransition, + staggerDirection: -1, + }, + }, + } +} export function TextEffect({ - children, - per = 'word', - as = 'p', - variants, - className, - preset = 'fade', - delay = 0, - speedReveal = 1, - speedSegment = 1, - trigger = true, - onAnimationComplete, - onAnimationStart, - segmentWrapperClassName, - containerTransition, - segmentTransition, - style, + children, + per = "word", + as = "p", + variants, + className, + preset = "fade", + delay = 0, + speedReveal = 1, + speedSegment = 1, + trigger = true, + onAnimationComplete, + onAnimationStart, + segmentWrapperClassName, + containerTransition, + segmentTransition, + style, }: TextEffectProps) { - const segments = splitText(children, per); - const MotionTag = motion[as as keyof typeof motion] as typeof motion.div; + const segments = splitText(children, per) + const MotionTag = motion[as as keyof typeof motion] as typeof motion.div - const baseVariants = preset - ? presetVariants[preset] - : { container: defaultContainerVariants, item: defaultItemVariants }; + const baseVariants = preset + ? presetVariants[preset] + : { container: defaultContainerVariants, item: defaultItemVariants } - const stagger = defaultStaggerTimes[per] / speedReveal; + const stagger = defaultStaggerTimes[per] / speedReveal - const baseDuration = 0.3 / speedSegment; + const baseDuration = 0.3 / speedSegment - const customStagger = hasTransition(variants?.container?.visible ?? {}) - ? (variants?.container?.visible as TargetAndTransition).transition - ?.staggerChildren - : undefined; + const customStagger = hasTransition(variants?.container?.visible ?? {}) + ? (variants?.container?.visible as TargetAndTransition).transition + ?.staggerChildren + : undefined - const customDelay = hasTransition(variants?.container?.visible ?? {}) - ? (variants?.container?.visible as TargetAndTransition).transition - ?.delayChildren - : undefined; + const customDelay = hasTransition(variants?.container?.visible ?? {}) + ? (variants?.container?.visible as TargetAndTransition).transition + ?.delayChildren + : undefined - const computedVariants = { - container: createVariantsWithTransition( - variants?.container || baseVariants.container, - { - staggerChildren: customStagger ?? stagger, - delayChildren: customDelay ?? delay, - ...containerTransition, - exit: { - staggerChildren: customStagger ?? stagger, - staggerDirection: -1, - }, - } - ), - item: createVariantsWithTransition(variants?.item || baseVariants.item, { - duration: baseDuration, - ...segmentTransition, - }), - }; + const computedVariants = { + container: createVariantsWithTransition( + variants?.container || baseVariants.container, + { + staggerChildren: customStagger ?? stagger, + delayChildren: customDelay ?? delay, + ...containerTransition, + exit: { + staggerChildren: customStagger ?? stagger, + staggerDirection: -1, + }, + }, + ), + item: createVariantsWithTransition(variants?.item || baseVariants.item, { + duration: baseDuration, + ...segmentTransition, + }), + } - return ( - - {trigger && ( - - {per !== 'line' ? {children} : null} - {segments.map((segment, index) => ( - - ))} - - )} - - ); + return ( + + {trigger && ( + + {per !== "line" ? {children} : null} + {segments.map((segment, index) => ( + + ))} + + )} + + ) } diff --git a/apps/web/components/views/add-memory/index.tsx b/apps/web/components/views/add-memory/index.tsx index f7940bce..4e250b53 100644 --- a/apps/web/components/views/add-memory/index.tsx +++ b/apps/web/components/views/add-memory/index.tsx @@ -361,7 +361,7 @@ export function AddMemoryView({ return { previousMemories, optimisticId: optimisticMemory.id } }, // If the mutation fails, roll back to the previous value - onError: (error, variables, context) => { + onError: (_error, variables, context) => { if (context?.previousMemories) { queryClient.setQueryData( ["documents-with-memories", variables.project], @@ -551,6 +551,7 @@ export function AddMemoryView({ className="w-[100vw] max-w-4xl sm:max-w-4xl backdrop-blur-xl border-white/10 z-[80] h-[52vh] overflow-y-auto p-4" showCloseButton={false} > + Add Memory setActiveTab(value as typeof activeTab)} @@ -638,9 +639,13 @@ export function AddMemoryView({ > {({ state, handleChange, handleBlur }) => ( <> -
- + -
{ e.preventDefault() e.stopPropagation() fileUploadForm.handleSubmit() }} - className="h-full flex flex-col" - > + className="h-full flex flex-col" + >
-
+
{/* Left side - Project Selection */} { return [...conversations].sort((a, b) => a.lastUpdated < b.lastUpdated ? 1 : -1, - ); - }, [conversations]); + ) + }, [conversations]) function handleNewChat() { - analytics.newChatStarted(); - const newId = crypto.randomUUID(); - setCurrentChatId(newId); - setIsDialogOpen(false); + analytics.newChatStarted() + const newId = crypto.randomUUID() + setCurrentChatId(newId) + setIsDialogOpen(false) } function formatRelativeTime(isoString: string): string { - return formatDistanceToNow(new Date(isoString), { addSuffix: true }); + return formatDistanceToNow(new Date(isoString), { addSuffix: true }) } return ( @@ -74,18 +74,17 @@ export function ChatRewrite() {
{sorted.map((c) => { - const isActive = c.id === currentChatId; + const isActive = c.id === currentChatId return ( -
{ - setCurrentChatId(c.id); - setIsDialogOpen(false); + setCurrentChatId(c.id) + setIsDialogOpen(false) }} className={cn( - "flex items-center justify-between rounded-md px-3 py-2 outline-none", + "flex items-center justify-between rounded-md px-3 py-2 outline-none w-full text-left", "transition-colors", isActive ? "bg-primary/10" : "hover:bg-muted", )} @@ -111,15 +110,15 @@ export function ChatRewrite() { variant="ghost" size="icon" onClick={(e) => { - e.stopPropagation(); - analytics.chatDeleted(); + e.stopPropagation() + analytics.chatDeleted() }} aria-label="Delete conversation" > -
- ); + + ) })} {sorted.length === 0 && (
@@ -152,5 +151,5 @@ export function ChatRewrite() {
- ); + ) } diff --git a/apps/web/globals.css b/apps/web/globals.css index 2c150cf0..f95da3a2 100644 --- a/apps/web/globals.css +++ b/apps/web/globals.css @@ -1,7 +1,6 @@ @import "tailwindcss"; @plugin "@tailwindcss/typography"; - .sm-tweet-theme .react-tweet-theme { --tweet-container-margin: 0px; } diff --git a/apps/web/middleware.ts b/apps/web/middleware.ts index bbb63c42..7bab1d21 100644 --- a/apps/web/middleware.ts +++ b/apps/web/middleware.ts @@ -4,6 +4,7 @@ import { NextResponse } from "next/server" export default async function proxy(request: Request) { console.debug("[PROXY] === PROXY START ===") const url = new URL(request.url) + console.debug("[PROXY] Path:", url.pathname) console.debug("[PROXY] Method:", request.method)