From 10ada4a1e21ff913ab8edc58ca71039d91cc0ece Mon Sep 17 00:00:00 2001
From: MaheshtheDev <38828053+MaheshtheDev@users.noreply.github.com>
Date: Sun, 9 Nov 2025 07:32:51 +0000
Subject: fix(web): sentry issues across the web app (#570)
Fixes all following sentry issues
- CONSUMER-APP-FF
- CONSUMER-APP-1T
- CONSUMER-APP-86
- CONSUMER-APP-7H
- CONSUMER-APP-4F
- CONSUMER-APP-7X
---
apps/web/components/graph-dialog.tsx | 3 +
apps/web/components/memories.tsx | 99 ++++++++++++------------
apps/web/components/views/chat/chat-messages.tsx | 55 +++++++++++--
apps/web/stores/chat.ts | 2 +-
packages/lib/auth-context.tsx | 30 ++++---
packages/lib/posthog.tsx | 29 ++++---
packages/ui/memory-graph/graph-webgl-canvas.tsx | 1 +
packages/ui/pages/login.tsx | 56 ++++++++++++--
8 files changed, 191 insertions(+), 84 deletions(-)
diff --git a/apps/web/components/graph-dialog.tsx b/apps/web/components/graph-dialog.tsx
index 9378b592..2e74b3b1 100644
--- a/apps/web/components/graph-dialog.tsx
+++ b/apps/web/components/graph-dialog.tsx
@@ -62,6 +62,9 @@ export function GraphDialog() {
return response.data
},
getNextPageParam: (lastPage, allPages) => {
+ if (!lastPage || !lastPage.pagination) return undefined
+ if (!Array.isArray(allPages)) return undefined
+
const loaded = allPages.reduce(
(acc, p) => acc + (p.documents?.length ?? 0),
0,
diff --git a/apps/web/components/memories.tsx b/apps/web/components/memories.tsx
index 161d4f14..faf146c5 100644
--- a/apps/web/components/memories.tsx
+++ b/apps/web/components/memories.tsx
@@ -60,6 +60,9 @@ export function Memories() {
return response.data
},
getNextPageParam: (lastPage, allPages) => {
+ if (!lastPage || !lastPage.pagination) return undefined
+ if (!Array.isArray(allPages)) return undefined
+
const loaded = allPages.reduce(
(acc, p) => acc + (p.documents?.length ?? 0),
0,
@@ -177,42 +180,22 @@ export function Memories() {
}
return (
- <>
-
-
-
- {!isMobile ? (
-
-
-
-
-
-
-
-
-
- ) : (
+
+
+
+ {!isMobile ? (
+
@@ -221,6 +204,7 @@ export function Memories() {
onClick={(e) => {
e.stopPropagation()
setShowAddMemoryView(true)
+ setShowConnectAIModal(false)
}}
type="button"
>
@@ -229,17 +213,34 @@ export function Memories() {
- )}
-
-
-
- {showAddMemoryView && (
-
setShowAddMemoryView(false)}
- />
- )}
-
- >
+
+ ) : (
+
+
+
+
+
+
+
+ )}
+
+
+
+ {showAddMemoryView && (
+
setShowAddMemoryView(false)}
+ />
+ )}
+
)
-}
\ No newline at end of file
+}
diff --git a/apps/web/components/views/chat/chat-messages.tsx b/apps/web/components/views/chat/chat-messages.tsx
index ff4eca34..0c795ec0 100644
--- a/apps/web/components/views/chat/chat-messages.tsx
+++ b/apps/web/components/views/chat/chat-messages.tsx
@@ -1,6 +1,6 @@
"use client"
-import { useChat, useCompletion } from "@ai-sdk/react"
+import { useChat, useCompletion, type UIMessage } from "@ai-sdk/react"
import { cn } from "@lib/utils"
import { Button } from "@ui/components/button"
import { DefaultChatTransport } from "ai"
@@ -21,6 +21,7 @@ import { usePersistentChat, useProject } from "@/stores"
import { useGraphHighlights } from "@/stores/highlights"
import { modelNames, ModelIcon } from "@/lib/models"
import { Spinner } from "../../spinner"
+import { areUIMessageArraysEqual } from "@/stores/chat"
interface MemoryResult {
documentId?: string
@@ -247,6 +248,10 @@ export function ChatMessages() {
const activeChatIdRef = useRef(null)
const shouldGenerateTitleRef = useRef(false)
const hasRunInitialMessageRef = useRef(false)
+ const lastSavedMessagesRef = useRef(null)
+ const lastSavedActiveIdRef = useRef(null)
+ const lastLoadedChatIdRef = useRef(null)
+ const lastLoadedMessagesRef = useRef(null)
const { setDocumentIds } = useGraphHighlights()
@@ -282,6 +287,10 @@ export function ChatMessages() {
},
})
+ useEffect(() => {
+ lastLoadedMessagesRef.current = messages
+ }, [messages])
+
useEffect(() => {
activeChatIdRef.current = currentChatId ?? id ?? null
}, [currentChatId, id])
@@ -326,20 +335,56 @@ export function ChatMessages() {
}, [id, currentChatId, setCurrentChatId])
useEffect(() => {
+ if (currentChatId !== lastLoadedChatIdRef.current) {
+ lastLoadedMessagesRef.current = null
+ lastSavedMessagesRef.current = null
+ }
+
+ if (currentChatId === lastLoadedChatIdRef.current) {
+ setInput("")
+ return
+ }
+
const msgs = getCurrentConversation()
+
if (msgs && msgs.length > 0) {
- setMessages(msgs)
+ const currentMessages = lastLoadedMessagesRef.current
+ if (!currentMessages || !areUIMessageArraysEqual(currentMessages, msgs)) {
+ lastLoadedMessagesRef.current = msgs
+ setMessages(msgs)
+ }
} else if (!currentChatId) {
- setMessages([])
+ if (
+ lastLoadedMessagesRef.current &&
+ lastLoadedMessagesRef.current.length > 0
+ ) {
+ lastLoadedMessagesRef.current = []
+ setMessages([])
+ }
}
+
+ lastLoadedChatIdRef.current = currentChatId
setInput("")
}, [currentChatId, getCurrentConversation, setMessages])
useEffect(() => {
const activeId = currentChatId ?? id
- if (activeId && messages.length > 0) {
- setConversation(activeId, messages)
+ if (!activeId || messages.length === 0) {
+ return
}
+
+ if (activeId !== lastSavedActiveIdRef.current) {
+ lastSavedMessagesRef.current = null
+ lastSavedActiveIdRef.current = activeId
+ }
+
+ const lastSaved = lastSavedMessagesRef.current
+ if (lastSaved && areUIMessageArraysEqual(lastSaved, messages)) {
+ return
+ }
+
+ lastSavedMessagesRef.current = messages
+ setConversation(activeId, messages)
}, [messages, currentChatId, id, setConversation])
const { complete } = useCompletion({
diff --git a/apps/web/stores/chat.ts b/apps/web/stores/chat.ts
index f1701139..24f4084b 100644
--- a/apps/web/stores/chat.ts
+++ b/apps/web/stores/chat.ts
@@ -7,7 +7,7 @@ import { indexedDBStorage } from "./indexeddb-storage"
/**
* Deep equality check for UIMessage arrays to prevent unnecessary state updates
*/
-function areUIMessageArraysEqual(a: UIMessage[], b: UIMessage[]): boolean {
+export function areUIMessageArraysEqual(a: UIMessage[], b: UIMessage[]): boolean {
if (a === b) return true
if (a.length !== b.length) return false
diff --git a/packages/lib/auth-context.tsx b/packages/lib/auth-context.tsx
index 7e6462fa..db24ec45 100644
--- a/packages/lib/auth-context.tsx
+++ b/packages/lib/auth-context.tsx
@@ -38,17 +38,23 @@ export function AuthProvider({ children }: { children: ReactNode }) {
// biome-ignore lint/correctness/useExhaustiveDependencies: ignoring the setActiveOrg dependency
useEffect(() => {
if (session?.session.activeOrganizationId) {
- authClient.organization.getFullOrganization().then((org) => {
- // TODO: Uncomment this when we have a way to handle consumer organizations better way
- //if (org.metadata?.isConsumer === true) {
- setOrg(org)
- //} else {
- // const consumerOrg = orgs?.find((o) => o.metadata?.isConsumer === true)
- // if (consumerOrg) {
- // setActiveOrg(consumerOrg.slug)
- // }
- //}
- })
+ authClient.organization
+ .getFullOrganization()
+ .then((org) => {
+ // TODO: Uncomment this when we have a way to handle consumer organizations better way
+ //if (org.metadata?.isConsumer === true) {
+ setOrg(org)
+ //} else {
+ // const consumerOrg = orgs?.find((o) => o.metadata?.isConsumer === true)
+ // if (consumerOrg) {
+ // setActiveOrg(consumerOrg.slug)
+ // }
+ //}
+ })
+ .catch((error) => {
+ // Silently handle organization fetch failures to prevent unhandled rejections
+ console.error("Failed to fetch organization:", error)
+ })
}
}, [session?.session.activeOrganizationId, orgs])
@@ -68,7 +74,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
if (pendingMethod) {
const now = Date.now()
- const ts = pendingTsRaw ? Number.parseInt(pendingTsRaw, 10) : NaN
+ const ts = pendingTsRaw ? Number.parseInt(pendingTsRaw, 10) : Number.NaN
const isFresh = Number.isFinite(ts) && now - ts < 10 * 60 * 1000 // 10 minutes TTL
if (isFresh) {
diff --git a/packages/lib/posthog.tsx b/packages/lib/posthog.tsx
index 62a60e09..0c436e1e 100644
--- a/packages/lib/posthog.tsx
+++ b/packages/lib/posthog.tsx
@@ -22,7 +22,7 @@ function PostHogPageTracking() {
$current_url: url,
path: pathname,
search_params: searchParams.toString(),
- page_type: getPageType(pathname),
+ page_type: getPageType(),
org_slug: getOrgSlug(pathname),
}
@@ -39,16 +39,21 @@ export function PostHogProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
if (typeof window !== "undefined") {
const posthogKey = process.env.NEXT_PUBLIC_POSTHOG_KEY
- if (posthogKey){
- posthog.init(posthogKey, {
- api_host: process.env.NEXT_PUBLIC_BACKEND_URL + "/orange",
- ui_host: "https://us.i.posthog.com",
- person_profiles: "identified_only",
- capture_pageview: false,
- capture_pageleave: true,
- })}
- else{
- console.warn("PostHog API key is not set. PostHog will not be initialized.")
+ const backendUrl =
+ process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"
+
+ if (posthogKey) {
+ posthog.init(posthogKey, {
+ api_host: `${backendUrl}/orange`,
+ ui_host: "https://us.i.posthog.com",
+ person_profiles: "identified_only",
+ capture_pageview: false,
+ capture_pageleave: true,
+ })
+ } else {
+ console.warn(
+ "PostHog API key is not set. PostHog will not be initialized.",
+ )
}
}
}, [])
@@ -75,7 +80,7 @@ export function PostHogProvider({ children }: { children: React.ReactNode }) {
)
}
-function getPageType(pathname: string): string {
+function getPageType(): string {
return "other"
}
diff --git a/packages/ui/memory-graph/graph-webgl-canvas.tsx b/packages/ui/memory-graph/graph-webgl-canvas.tsx
index 480d1d6b..af13eefc 100644
--- a/packages/ui/memory-graph/graph-webgl-canvas.tsx
+++ b/packages/ui/memory-graph/graph-webgl-canvas.tsx
@@ -761,6 +761,7 @@ export const GraphWebGLCanvas = memo(
}}
>
{
if (params.get("error")) {
@@ -121,13 +142,10 @@ export function LoginPage({
method: "magic_link",
error: error instanceof Error ? error.message : "Unknown error",
email_domain: email.split("@")[1] || "unknown",
+ is_network_error: isNetworkError(error),
});
- setError(
- error instanceof Error
- ? error.message
- : "Failed to send login link. Please try again.",
- );
+ setError(getErrorMessage(error));
setIsLoading(false);
setIsLoadingEmail(false);
return;
@@ -321,6 +339,7 @@ export function LoginPage({
onClick={() => {
if (isLoading) return;
setIsLoading(true);
+ setError(null);
posthog.capture("login_attempt", {
method: "social",
provider: "google",
@@ -331,6 +350,19 @@ export function LoginPage({
callbackURL: getCallbackURL(),
provider: "google",
})
+ .catch((error) => {
+ console.error("Google login error:", error);
+ posthog.capture("login_failed", {
+ method: "social",
+ provider: "google",
+ error:
+ error instanceof Error
+ ? error.message
+ : "Unknown error",
+ is_network_error: isNetworkError(error),
+ });
+ setError(getErrorMessage(error));
+ })
.finally(() => {
setIsLoading(false);
});
@@ -385,6 +417,7 @@ export function LoginPage({
onClick={() => {
if (isLoading) return;
setIsLoading(true);
+ setError(null);
posthog.capture("login_attempt", {
method: "social",
provider: "github",
@@ -395,6 +428,19 @@ export function LoginPage({
callbackURL: getCallbackURL(),
provider: "github",
})
+ .catch((error) => {
+ console.error("GitHub login error:", error);
+ posthog.capture("login_failed", {
+ method: "social",
+ provider: "github",
+ error:
+ error instanceof Error
+ ? error.message
+ : "Unknown error",
+ is_network_error: isNetworkError(error),
+ });
+ setError(getErrorMessage(error));
+ })
.finally(() => {
setIsLoading(false);
});
--
cgit v1.2.3