diff --git a/apps/mail/components/mail/mail-display.tsx b/apps/mail/components/mail/mail-display.tsx index fdd71583e..3aea5a543 100644 --- a/apps/mail/components/mail/mail-display.tsx +++ b/apps/mail/components/mail/mail-display.tsx @@ -643,7 +643,8 @@ const MoreAboutPerson = ({ } = useMutation(trpc.ai.webSearch.mutationOptions()); const handleSearch = useCallback(() => { doSearch({ - query: `In 100 words or less: What is the background of ${person.name} & ${person.email}, of ${person.email.split('@')[1]}. `, + query: `In 100 words or less: What is the background of ${person.name} & ${person.email}, of ${person.email.split('@')[1]}. + This could be a phishing email address, indicate if the domain is suspicious, example: x.io is not a valid domain for x.com | example: x.com is a valid domain for x.com | example: paypalcom.com is not a valid domain for paypal.com`, }); }, [person.name]); diff --git a/apps/mail/components/ui/nav-main.tsx b/apps/mail/components/ui/nav-main.tsx index 2598d2cd3..444c19b41 100644 --- a/apps/mail/components/ui/nav-main.tsx +++ b/apps/mail/components/ui/nav-main.tsx @@ -18,11 +18,13 @@ import { Collapsible, CollapsibleTrigger } from '@/components/ui/collapsible'; import { useActiveConnection, useConnections } from '@/hooks/use-connections'; import { type MessageKey, type NavItem } from '@/config/navigation'; import { LabelDialog } from '@/components/labels/label-dialog'; +import { useMutation, useQuery } from '@tanstack/react-query'; +import Intercom, { show } from '@intercom/messenger-js-sdk'; +import { CurvedArrow, MessageSquare } from '../icons/icons'; import { useSearchValue } from '@/hooks/use-search-value'; import { useSidebar } from '../context/sidebar-context'; import { useTRPC } from '@/providers/query-provider'; import { RecursiveFolder } from './recursive-folder'; -import { useMutation } from '@tanstack/react-query'; import type { Label as LabelType } from '@/types'; import { Link, useLocation } from 'react-router'; import { Button } from '@/components/ui/button'; @@ -32,7 +34,6 @@ import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import { useStats } from '@/hooks/use-stats'; import SidebarLabels from './sidebar-labels'; -import { CurvedArrow } from '../icons/icons'; import { Command, Plus } from 'lucide-react'; import { Tree } from '../magicui/file-tree'; import { useCallback, useRef } from 'react'; @@ -76,14 +77,20 @@ export function NavMain({ items }: NavMainProps) { const pathname = location.pathname; const searchParams = new URLSearchParams(); const [category] = useQueryState('category'); - - const [isDialogOpen, setIsDialogOpen] = React.useState(false); - const { data: session } = useSession(); const { data: connections } = useConnections(); const { data: stats } = useStats(); const { data: activeConnection } = useActiveConnection(); - const trpc = useTRPC(); + const { data: intercomToken } = useQuery(trpc.user.getIntercomToken.queryOptions()); + + React.useEffect(() => { + if (intercomToken) { + Intercom({ + app_id: 'aavenrba', + intercom_user_jwt: intercomToken, + }); + } + }, [intercomToken]); const { mutateAsync: createLabel } = useMutation(trpc.labels.create.mutationOptions()); @@ -189,9 +196,10 @@ export function NavMain({ items }: NavMainProps) { }, [pathname, searchParams], ); + const t = useTranslations(); const onSubmit = async (data: LabelType) => { - await toast.promise(createLabel(data), { + toast.promise(createLabel(data), { loading: 'Creating label...', success: 'Label created successfully', error: 'Failed to create label', @@ -201,6 +209,27 @@ export function NavMain({ items }: NavMainProps) { return ( + {isBottomNav ? ( + <> + show()} + tooltip={state === 'collapsed' ? t('help' as MessageKey) : undefined} + className="flex cursor-pointer items-center" + > + +

Help

+
+ + + ) : null} {items.map((section) => ( { @@ -11,4 +12,14 @@ export const userRouter = router({ }); return { success, message }; }), + getIntercomToken: privateProcedure.query(async ({ ctx }) => { + const token = await jwt.sign( + { + user_id: ctx.session.user.id, + email: ctx.session.user.email, + }, + ctx.c.env.JWT_SECRET, + ); + return token; + }), }); diff --git a/apps/server/wrangler.jsonc b/apps/server/wrangler.jsonc index 4a07bf064..a48f88d01 100644 --- a/apps/server/wrangler.jsonc +++ b/apps/server/wrangler.jsonc @@ -66,6 +66,7 @@ "COOKIE_DOMAIN": "localhost", "VITE_PUBLIC_BACKEND_URL": "http://localhost:8787", "VITE_PUBLIC_APP_URL": "http://localhost:3000", + "JWT_SECRET": "secret", }, "kv_namespaces": [ { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 92ac4b1cd..ac49f63ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -109,6 +109,9 @@ importers: '@hookform/resolvers': specifier: 4.1.2 version: 4.1.2(react-hook-form@7.54.2(react@19.1.0)) + '@intercom/messenger-js-sdk': + specifier: 0.0.14 + version: 0.0.14 '@react-email/components': specifier: ^0.0.36 version: 0.0.36(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -482,6 +485,9 @@ importers: '@trpc/server': specifier: 'catalog:' version: 11.1.4(typescript@5.8.3) + '@tsndr/cloudflare-worker-jwt': + specifier: 3.2.0 + version: 3.2.0 '@upstash/ratelimit': specifier: ^2.0.5 version: 2.0.5(@upstash/redis@1.34.9) @@ -1599,6 +1605,9 @@ packages: cpu: [x64] os: [win32] + '@intercom/messenger-js-sdk@0.0.14': + resolution: {integrity: sha512-2dH4BDAh9EI90K7hUkAdZ76W79LM45Sd1OBX7t6Vzy8twpNiQ5X+7sH9G5hlJlkSGnf+vFWlFcy9TOYAyEs1hA==} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -3413,6 +3422,9 @@ packages: react-dom: '>=18.2.0' typescript: '>=5.7.2' + '@tsndr/cloudflare-worker-jwt@3.2.0': + resolution: {integrity: sha512-y45452JzKxFDfCUHNGrdgIcrJTkYa6xtrKtCQTjKj+hjzw8dOHF9R0uGuU8WxvCCMi4sMzZ1KREnZTsTy7DsiQ==} + '@types/accept-language-parser@1.5.8': resolution: {integrity: sha512-6+dKdh9q/I8xDBnKQKddCBKaWBWLmJ97HTiSbAXVpL7LEgDfOkKF98UVCaZ5KJrtdN5Wa5ndXUiqD3XR9XGqWQ==} @@ -8117,6 +8129,8 @@ snapshots: '@img/sharp-win32-x64@0.34.2': optional: true + '@intercom/messenger-js-sdk@0.0.14': {} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -10041,6 +10055,8 @@ snapshots: react-dom: 19.1.0(react@19.1.0) typescript: 5.8.3 + '@tsndr/cloudflare-worker-jwt@3.2.0': {} + '@types/accept-language-parser@1.5.8': {} '@types/canvas-confetti@1.9.0': {}