From ba8eb52b94bce998f78ae41a20e21200d4a962c4 Mon Sep 17 00:00:00 2001 From: Dhravya Shah Date: Sun, 17 May 2026 00:15:37 -0700 Subject: [PATCH] Show own space as Your conversations (#956) --- apps/web/components/dashboard-view.tsx | 10 +++++-- apps/web/components/select-spaces-modal.tsx | 32 +++++++++++++++------ apps/web/components/space-selector.tsx | 16 +++++++++-- apps/web/hooks/use-personalization.ts | 18 +++++++++--- apps/web/lib/ingest-auto-space.ts | 14 +++++++++ 5 files changed, 73 insertions(+), 17 deletions(-) diff --git a/apps/web/components/dashboard-view.tsx b/apps/web/components/dashboard-view.tsx index 2632446d..411f0b89 100644 --- a/apps/web/components/dashboard-view.tsx +++ b/apps/web/components/dashboard-view.tsx @@ -723,10 +723,16 @@ export function DashboardView({ firstName, ) + const [tipIndex, setTipIndex] = useState(0) + + useEffect(() => { + setTipIndex(Math.floor(Math.random() * TIPS[profession].length)) + }, [profession]) + const tip = useMemo(() => { const tips = TIPS[profession] - return tips[Math.floor(Math.random() * tips.length)] - }, [profession]) + return tips[tipIndex % tips.length] ?? tips[0] + }, [profession, tipIndex]) return (
( null, @@ -455,15 +456,19 @@ export function SelectSpacesModal({ return byCategory.filter((p) => { const plugin = detectPluginSpace(p.containerTag) const projectName = pluginMetaMap.get(p.containerTag)?.projectName + const displayName = spaceSelectorDisplayName(p, p.containerTag, { + currentUserId: user?.id, + }) return ( p.containerTag.toLowerCase().includes(query) || (p.name ?? "").toLowerCase().includes(query) || + displayName.toLowerCase().includes(query) || (plugin?.label.toLowerCase().includes(query) ?? false) || (plugin?.projectId?.toLowerCase().includes(query) ?? false) || (projectName?.toLowerCase().includes(query) ?? false) ) }) - }, [allSpaces, activeCategory, searchQuery, pluginMetaMap]) + }, [allSpaces, activeCategory, searchQuery, pluginMetaMap, user?.id]) const recentProjects = useMemo(() => { if (!recents?.length) return [] @@ -551,10 +556,12 @@ export function SelectSpacesModal({ ) .map((project) => ({ id: project.id, - name: project.name ?? project.containerTag, + name: spaceSelectorDisplayName(project, project.containerTag, { + currentUserId: user?.id, + }), containerTag: project.containerTag, })), - [allSpaces, bulkDeleteTags], + [allSpaces, bulkDeleteTags, user?.id], ) const bulkDeleteCount = bulkDeleteProjects.length @@ -567,8 +574,16 @@ export function SelectSpacesModal({ project.containerTag, )?.projectName const pluginIdLabel = pluginProjectName || plugin?.projectId + const displayName = spaceSelectorDisplayName( + project, + project.containerTag, + { + currentUserId: user?.id, + }, + ) const isDefault = project.containerTag === DEFAULT_PROJECT_ID - const canEdit = !isDefault && !plugin + const isOwnSpace = isOwnConversationSpace(project, user?.id) + const canEdit = !isDefault && !plugin && !isOwnSpace const canBulkDelete = enableDelete && !isDefault const isEditing = editingProject?.containerTag === project.containerTag const isBulkDeleteSelected = bulkDeleteTags.has(project.containerTag) @@ -697,7 +712,7 @@ export function SelectSpacesModal({ )} {plugin ? ( <> @@ -709,7 +724,7 @@ export function SelectSpacesModal({ )} ) : ( - spaceSelectorDisplayName(project, project.containerTag) + displayName )} @@ -738,7 +753,7 @@ export function SelectSpacesModal({ e.stopPropagation() onDeleteRequest({ id: project.id, - name: project.name ?? project.containerTag, + name: displayName, containerTag: project.containerTag, }) }} @@ -766,6 +781,7 @@ export function SelectSpacesModal({ startEditing, toggleBulkDeleteTag, updateProjectMutation.isPending, + user?.id, ], ) diff --git a/apps/web/components/space-selector.tsx b/apps/web/components/space-selector.tsx index 689219b1..40d5947e 100644 --- a/apps/web/components/space-selector.tsx +++ b/apps/web/components/space-selector.tsx @@ -31,6 +31,7 @@ import { } from "@repo/ui/components/select" import { Button } from "@repo/ui/components/button" import { Tooltip, TooltipContent, TooltipTrigger } from "@ui/components/tooltip" +import { useAuth } from "@lib/auth-context" import { analytics } from "@/lib/analytics" import { compareSpacesUserFirst, @@ -135,6 +136,7 @@ export function SpaceSelector({ const { deleteProjectMutation, deleteProjectsMutation } = useProjectMutations() const { allProjects, isLoading } = useContainerTags() + const { user } = useAuth() useEffect(() => { setRecents(readRecents()) @@ -199,12 +201,14 @@ export function SpaceSelector({ ? idForLabel ? `${plugin.label} ยท ${idForLabel}` : plugin.label - : spaceSelectorDisplayName(found, containerTag), + : spaceSelectorDisplayName(found, containerTag, { + currentUserId: user?.id, + }), emoji: found?.emoji || "๐Ÿ“", plugin, isAuto: false, } - }, [allProjects, selectedProjects, pluginMetaMap, includeAuto]) + }, [allProjects, selectedProjects, pluginMetaMap, includeAuto, user?.id]) const pushRecent = useCallback((tag: string) => { setRecents((prev) => { @@ -615,7 +619,13 @@ export function SpaceSelector({ )} ) : ( - spaceSelectorDisplayName(p, p.containerTag) + spaceSelectorDisplayName( + p, + p.containerTag, + { + currentUserId: user?.id, + }, + ) )} diff --git a/apps/web/hooks/use-personalization.ts b/apps/web/hooks/use-personalization.ts index 256fab3c..619b3ac2 100644 --- a/apps/web/hooks/use-personalization.ts +++ b/apps/web/hooks/use-personalization.ts @@ -2,7 +2,7 @@ import { useState, useEffect, useCallback } from "react" import { $fetch } from "@lib/api" -import type { SearchResult } from "@repo/lib/api" +import type { SearchResult } from "@repo/validation/api" const CACHE_KEY = "sm_profession_v1" const CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000 @@ -235,6 +235,15 @@ function pickCopy(p: Profession): PersonalizedCopy { } } +function defaultCopy(p: Profession): PersonalizedCopy { + const pool = COPY_POOLS[p] + return { + saveLink: pool.saveLink[0] ?? "", + writeNote: pool.writeNote[0] ?? "", + chatPlaceholder: pool.chatPlaceholder[0] ?? "", + } +} + const sessionCopyCache: Partial> = {} function getSessionCopy(p: Profession): PersonalizedCopy { @@ -398,7 +407,7 @@ export function usePersonalization(): { setProfession: (p: Profession) => void } { const [copy, setCopy] = useState(() => - getSessionCopy("default"), + defaultCopy("default"), ) const [profession, setProfessionState] = useState("default") @@ -410,8 +419,9 @@ export function usePersonalization(): { ) } catch {} // Re-pick on explicit change so the user sees fresh copy for the new identity - sessionCopyCache[p] = pickCopy(p) - setCopy(sessionCopyCache[p]!) + const freshCopy = pickCopy(p) + sessionCopyCache[p] = freshCopy + setCopy(freshCopy) setProfessionState(p) }, []) diff --git a/apps/web/lib/ingest-auto-space.ts b/apps/web/lib/ingest-auto-space.ts index 9768a27e..3f38a85a 100644 --- a/apps/web/lib/ingest-auto-space.ts +++ b/apps/web/lib/ingest-auto-space.ts @@ -1,6 +1,8 @@ import { DEFAULT_PROJECT_ID } from "@lib/constants" import type { ContainerTagListType } from "@lib/types" +export const OWN_CONVERSATIONS_SPACE_NAME = "Your conversations" + /** * Spaces auto-created on first ingest use `name === \`Space ${containerTag}\`` * (mono `apps/api/src/routes/memories/handler-effect.ts`). Those are noisy in the @@ -24,10 +26,22 @@ export function compareSpacesUserFirst( ) } +export function isOwnConversationSpace( + p: Pick | undefined, + currentUserId?: string | null, +): boolean { + return !!currentUserId && p?.containerTag === currentUserId +} + export function spaceSelectorDisplayName( p: Pick | undefined, fallback: string, + options?: { currentUserId?: string | null }, ): string { + const containerTag = p?.containerTag ?? fallback + if (containerTag === options?.currentUserId) { + return OWN_CONVERSATIONS_SPACE_NAME + } if (!p) return fallback const name = p.name ?? p.containerTag const long = name.length > 44