diff --git a/public/assets/llamaai-1-light.png b/public/assets/llamaai-1-light.png new file mode 100644 index 000000000..007ff42e1 Binary files /dev/null and b/public/assets/llamaai-1-light.png differ diff --git a/public/assets/llamaai-1.png b/public/assets/llamaai-1.png new file mode 100644 index 000000000..10d293116 Binary files /dev/null and b/public/assets/llamaai-1.png differ diff --git a/public/assets/llamaai-2-light.png b/public/assets/llamaai-2-light.png new file mode 100644 index 000000000..37e8f613c Binary files /dev/null and b/public/assets/llamaai-2-light.png differ diff --git a/public/assets/llamaai-2.png b/public/assets/llamaai-2.png new file mode 100644 index 000000000..1c646a2d8 Binary files /dev/null and b/public/assets/llamaai-2.png differ diff --git a/public/assets/llamaai-3-light.png b/public/assets/llamaai-3-light.png new file mode 100644 index 000000000..450859b66 Binary files /dev/null and b/public/assets/llamaai-3-light.png differ diff --git a/public/assets/llamaai-3.png b/public/assets/llamaai-3.png new file mode 100644 index 000000000..76c71f42f Binary files /dev/null and b/public/assets/llamaai-3.png differ diff --git a/public/assets/llamaai.mp4 b/public/assets/llamaai.mp4 index fac6bcb01..1a271ef59 100644 Binary files a/public/assets/llamaai.mp4 and b/public/assets/llamaai.mp4 differ diff --git a/public/assets/poster.png b/public/assets/poster.png new file mode 100644 index 000000000..ea29a1282 Binary files /dev/null and b/public/assets/poster.png differ diff --git a/public/icons/ask-llamaai-1.svg b/public/icons/ask-llamaai-1.svg deleted file mode 100644 index a5bb47fed..000000000 --- a/public/icons/ask-llamaai-1.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/public/icons/ask-llamaai-3.svg b/public/icons/ask-llamaai-3.svg new file mode 100644 index 000000000..a639efaa5 --- /dev/null +++ b/public/icons/ask-llamaai-3.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/Modal/LlamaAIWelcomeModal.tsx b/src/components/Modal/LlamaAIWelcomeModal.tsx index bb4562362..42f5feb52 100644 --- a/src/components/Modal/LlamaAIWelcomeModal.tsx +++ b/src/components/Modal/LlamaAIWelcomeModal.tsx @@ -11,51 +11,47 @@ export function LlamaAIWelcomeModal({ isOpen, onClose }: LlamaAIWelcomeModalProp return ( !open && onClose()}> } portal unmountOnHide > -
-
- - +
- LlamaAI + + + LlamaAI +
-

Exclusive access to LlamaAI

- -

- As one of our longest active subscribers we've given you early access to LlamaAI, our biggest upcoming - product -

- -

- You can query our entire database, generate charts and more -

- -

- - Try it - {' '} - to be part of future early access previews +

+ Introducing LlamaAI 🚀 +

+

+ We're upgrading your subscription with LlamaAI. Turn data into deep, flexible analysis in a conversational + way.

- Go to LlamaAI + + + + Try LlamaAI
diff --git a/src/components/Nav/Desktop/shared.tsx b/src/components/Nav/Desktop/shared.tsx index b933fbb47..c510801d1 100644 --- a/src/components/Nav/Desktop/shared.tsx +++ b/src/components/Nav/Desktop/shared.tsx @@ -46,7 +46,7 @@ export const NavItemContent = React.memo(function NavItemContent({ ) : name === 'LlamaAI' ? ( - + ) : null} diff --git a/src/components/Nav/Mobile/Menu.tsx b/src/components/Nav/Mobile/Menu.tsx index 64fcaf22c..f10fdc6c3 100644 --- a/src/components/Nav/Mobile/Menu.tsx +++ b/src/components/Nav/Mobile/Menu.tsx @@ -346,11 +346,9 @@ const NavItemContent = React.memo(function NavItemContent({ {icon ? ( ) : name === 'LlamaAI' ? ( - LlamaAI + + + ) : null} {name} diff --git a/src/components/Nav/index.tsx b/src/components/Nav/index.tsx index 37cec16e5..25c4db48d 100644 --- a/src/components/Nav/index.tsx +++ b/src/components/Nav/index.tsx @@ -1,8 +1,8 @@ import { lazy, memo, Suspense, useMemo, useSyncExternalStore } from 'react' import { useGetLiteDashboards } from '~/containers/ProDashboard/hooks/useDashboardAPI' import { useAuthContext } from '~/containers/Subscribtion/auth' -import { useFeatureFlagsContext } from '~/contexts/FeatureFlagsContext' import { subscribeToPinnedMetrics, WALLET_LINK_MODAL } from '~/contexts/LocalStorage' +import { useSubscribe } from '~/hooks/useSubscribe' import defillamaPages from '~/public/pages.json' import { BasicLink } from '../Link' import { DesktopNav } from './Desktop' @@ -49,9 +49,9 @@ function NavComponent({ metricFilters }: { metricFilters?: { name: string; key: const { data: liteDashboards } = useGetLiteDashboards() const { user, isAuthenticated } = useAuthContext() - const { hasFeature } = useFeatureFlagsContext() + const { subscription } = useSubscribe() + const hasActiveSubscription = subscription?.status === 'active' - const hasLlamaAI = hasFeature('llamaai') const hasEthWallet = Boolean(user?.walletAddress) const hasSeenWalletPrompt = typeof window !== 'undefined' && window?.localStorage?.getItem(WALLET_LINK_MODAL) === 'true' @@ -62,10 +62,12 @@ function NavComponent({ metricFilters }: { metricFilters?: { name: string; key: const otherMainPages = [ { name: 'Pricing', route: '/subscription', icon: 'user', attention: showAttentionIcon }, { name: 'Custom Dashboards', route: '/pro', icon: 'blocks' }, - ...(hasLlamaAI ? [{ name: 'LlamaAI', route: '/ai', icon: '' }] : []) + ...(hasActiveSubscription + ? [{ name: 'LlamaAI', route: '/ai/chat', icon: '' }] + : [{ name: 'LlamaAI', route: '/ai', icon: '' }]) ] return [{ category: 'Main', pages: defillamaPages['Main'].concat(otherMainPages) }] - }, [showAttentionIcon, hasLlamaAI]) + }, [showAttentionIcon, hasActiveSubscription]) const userDashboards = useMemo( () => liteDashboards?.map(({ id, name }) => ({ name, route: `/pro/${id}` })) ?? [], diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 6e8d32bb1..a69dc62d7 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -5,9 +5,9 @@ import { instantMeiliSearch } from '@meilisearch/instant-meilisearch' import { useQuery } from '@tanstack/react-query' import { InstantSearch, useInstantSearch, useSearchBox } from 'react-instantsearch' import { LoadingDots } from '~/components/Loaders' -import { useFeatureFlagsContext } from '~/contexts/FeatureFlagsContext' import { subscribeToLocalStorage } from '~/contexts/LocalStorage' import { useIsClient } from '~/hooks' +import { useSubscribe } from '~/hooks/useSubscribe' import { fetchJson } from '~/utils/async' import { Icon } from '../Icon' import { BasicLink } from '../Link' @@ -77,75 +77,95 @@ const Mobile = () => { const { searchList, isLoadingSearchList, errorSearchList, defaultSearchList, recentSearchList } = useSearchList() + const router = useRouter() + + const { subscription } = useSubscribe() + const hasActiveSubscription = subscription?.status === 'active' + return ( - - - Search - - + <> + {!(router.pathname === '/ai' || router.pathname.startsWith('/ai/')) && ( + + + + + Ask LlamaAI + + )} + + + Search + + - - { - startTransition(() => { - refine(value) - }) - }} + - - - - - - + { + startTransition(() => { + refine(value) + }) + }} + > + + + + + + - - {query ? ( - status === 'loading' ? ( + + {query ? ( + status === 'loading' ? ( +

+ Loading + +

+ ) : error ? ( +

{`Error: ${error.message}`}

+ ) : !results?.hits?.length ? ( +

No results found

+ ) : ( + results.hits.map((route: ISearchItem) => ( + + )) + ) + ) : isLoadingSearchList ? (

Loading

- ) : error ? ( -

{`Error: ${error.message}`}

- ) : !results?.hits?.length ? ( + ) : errorSearchList ? ( +

{`Error: ${errorSearchList.message}`}

+ ) : !searchList?.length ? (

No results found

) : ( - results.hits.map((route: ISearchItem) => ( - - )) - ) - ) : isLoadingSearchList ? ( -

- Loading - -

- ) : errorSearchList ? ( -

{`Error: ${errorSearchList.message}`}

- ) : !searchList?.length ? ( -

No results found

- ) : ( - <> - {recentSearchList.map((route: ISearchItem) => ( - - ))} - {defaultSearchList.map((route: ISearchItem) => ( - - ))} - - )} -
-
-
-
+ <> + {recentSearchList.map((route: ISearchItem) => ( + + ))} + {defaultSearchList.map((route: ISearchItem) => ( + + ))} + + )} + + + +
+ ) } @@ -155,7 +175,8 @@ const Desktop = () => { const { query, refine } = useSearchBox() const { results, status, error } = useInstantSearch({ catchError: true }) - const { hasFeature, loading: featureFlagsLoading } = useFeatureFlagsContext() + const { subscription } = useSubscribe() + const hasActiveSubscription = subscription?.status === 'active' const [open, setOpen] = useState(false) const inputField = useRef(null) @@ -257,19 +278,19 @@ const Desktop = () => { - {!featureFlagsLoading && - hasFeature('llamaai') && - !(router.pathname === '/ai' || router.pathname.startsWith('/ai/')) && ( - - Ask LlamaAI - - - - - )} + {!(router.pathname === '/ai' || router.pathname.startsWith('/ai/')) && ( + + + + + Ask LlamaAI + + )} ) } diff --git a/src/components/SubscribeCards/FreeCard.tsx b/src/components/SubscribeCards/FreeCard.tsx index 10b134172..e85f029d4 100644 --- a/src/components/SubscribeCards/FreeCard.tsx +++ b/src/components/SubscribeCards/FreeCard.tsx @@ -27,6 +27,22 @@ export function FreeCard() { Access to all our data through the dashboard +
  • + + Access to LlamaAI +
  • +
  • + + Create Custom DefiLlama Pro Dashboards +
  • +
  • + + CSV data downloads +
  • +
  • + + Full access to LlamaFeed +
  • ) diff --git a/src/components/SubscribeCards/SubscribeProCard.tsx b/src/components/SubscribeCards/SubscribeProCard.tsx index e4bc1a9be..0c674ff40 100644 --- a/src/components/SubscribeCards/SubscribeProCard.tsx +++ b/src/components/SubscribeCards/SubscribeProCard.tsx @@ -1,4 +1,5 @@ -import { useState } from 'react' +import { useEffect, useState } from 'react' +import Link from 'next/link' import { useRouter } from 'next/router' import * as Ariakit from '@ariakit/react' import { Icon } from '~/components/Icon' @@ -55,21 +56,27 @@ export function SubscribeProCard({

    Multiple payment options

    )}