diff --git a/packages/shared/src/components/ProfileMenu/sections/MainSection.tsx b/packages/shared/src/components/ProfileMenu/sections/MainSection.tsx
index 9043bca3724..7ee1b64eab9 100644
--- a/packages/shared/src/components/ProfileMenu/sections/MainSection.tsx
+++ b/packages/shared/src/components/ProfileMenu/sections/MainSection.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import type { ReactElement } from 'react';
import { ProfileSection } from '../ProfileSection';
+import type { ProfileSectionItemProps } from '../ProfileSectionItem';
import {
AnalyticsIcon,
CoinIcon,
@@ -17,35 +18,37 @@ export const MainSection = (): ReactElement => {
const hasAccessToCores = useHasAccessToCores();
const { user } = useAuthContext();
- return (
-
- );
+ const items: ProfileSectionItemProps[] = [
+ {
+ title: 'Your profile',
+ href: `${webappUrl}${user?.username}`,
+ icon: UserIcon,
+ },
+ ...(hasAccessToCores
+ ? [
+ {
+ title: 'Core wallet',
+ href: walletUrl,
+ icon: CoinIcon,
+ } satisfies ProfileSectionItemProps,
+ ]
+ : []),
+ {
+ title: 'Achievements',
+ href: `${webappUrl}${user?.username}/achievements`,
+ icon: MedalBadgeIcon,
+ },
+ {
+ title: 'DevCard',
+ href: `${settingsUrl}/customization/devcard`,
+ icon: DevCardIcon,
+ },
+ {
+ title: 'Analytics',
+ href: `${webappUrl}analytics`,
+ icon: AnalyticsIcon,
+ },
+ ];
+
+ return ;
};
diff --git a/packages/shared/src/components/icons/Joystick/filled.svg b/packages/shared/src/components/icons/Joystick/filled.svg
new file mode 100644
index 00000000000..59bd3f9132c
--- /dev/null
+++ b/packages/shared/src/components/icons/Joystick/filled.svg
@@ -0,0 +1,4 @@
+
diff --git a/packages/shared/src/components/icons/Joystick/index.tsx b/packages/shared/src/components/icons/Joystick/index.tsx
new file mode 100644
index 00000000000..3bdaaabcc25
--- /dev/null
+++ b/packages/shared/src/components/icons/Joystick/index.tsx
@@ -0,0 +1,10 @@
+import type { ReactElement } from 'react';
+import React from 'react';
+import type { IconProps } from '../../Icon';
+import Icon from '../../Icon';
+import OutlinedIcon from './outlined.svg';
+import FilledIcon from './filled.svg';
+
+export const JoystickIcon = (props: IconProps): ReactElement => (
+
+);
diff --git a/packages/shared/src/components/icons/Joystick/outlined.svg b/packages/shared/src/components/icons/Joystick/outlined.svg
new file mode 100644
index 00000000000..437b196ac50
--- /dev/null
+++ b/packages/shared/src/components/icons/Joystick/outlined.svg
@@ -0,0 +1,4 @@
+
diff --git a/packages/shared/src/components/icons/index.ts b/packages/shared/src/components/icons/index.ts
index 88afa15506a..11cf7a5c9b3 100644
--- a/packages/shared/src/components/icons/index.ts
+++ b/packages/shared/src/components/icons/index.ts
@@ -80,6 +80,7 @@ export * from './Italic';
export * from './JetBrains';
export * from './Job';
export * from './JobStatus';
+export * from './Joystick';
export * from './Kaggle';
export * from './Key';
export * from './Label';
diff --git a/packages/shared/src/components/profile/ProfileSettingsMenu.tsx b/packages/shared/src/components/profile/ProfileSettingsMenu.tsx
index c6a27962ac8..8264f3c2fda 100644
--- a/packages/shared/src/components/profile/ProfileSettingsMenu.tsx
+++ b/packages/shared/src/components/profile/ProfileSettingsMenu.tsx
@@ -34,6 +34,7 @@ import {
TourIcon,
FeatherIcon,
GiftIcon,
+ JoystickIcon,
} from '../icons';
import { NavDrawer } from '../drawers/NavDrawer';
import {
@@ -188,6 +189,11 @@ const useAccountPageItems = ({ onClose }: { onClose?: () => void } = {}) => {
onClose?.();
},
},
+ gameCenter: {
+ title: 'Game Center',
+ icon: JoystickIcon,
+ href: `${webappUrl}game-center`,
+ },
trackAchievement: {
title: 'Track achievement',
icon: PinIcon,
@@ -438,7 +444,7 @@ export const InnerProfileSettingsMenu = ({
{
if (item.href === walletUrl && !hasAccessToCores) {
@@ -459,6 +465,13 @@ export const InnerProfileSettingsMenu = ({
return false;
}
+ if (
+ itemKey === 'gameCenter' &&
+ isQuestsFeatureEnabled !== true
+ ) {
+ return false;
+ }
+
return true;
})
.map(([, item]: [string, ProfileSectionItemProps]) => {
@@ -491,7 +504,7 @@ export function ProfileSettingsMenuMobile({
shouldKeepOpen={shouldKeepOpen}
drawerProps={{
isOpen,
- onClose,
+ onClose: onClose ?? (() => {}),
}}
>
@@ -499,7 +512,7 @@ export function ProfileSettingsMenuMobile({
);
}
-export function ProfileSettingsMenuDesktop(): ReactElement {
+export function ProfileSettingsMenuDesktop(): ReactElement | null {
const { user } = useAuthContext();
const featureTheme = useFeatureTheme();
diff --git a/packages/shared/src/components/sidebar/sections/MainSection.tsx b/packages/shared/src/components/sidebar/sections/MainSection.tsx
index a6e7d137818..46ec6e2ea8e 100644
--- a/packages/shared/src/components/sidebar/sections/MainSection.tsx
+++ b/packages/shared/src/components/sidebar/sections/MainSection.tsx
@@ -8,6 +8,7 @@ import {
EyeIcon,
HomeIcon,
HotIcon,
+ JoystickIcon,
SquadIcon,
TerminalIcon,
YearInReviewIcon,
@@ -24,6 +25,7 @@ import { useConditionalFeature } from '../../../hooks';
import {
featurePlusCtaCopy,
featureYearInReview,
+ questsFeature,
} from '../../../lib/featureManagement';
export const MainSection = ({
@@ -42,6 +44,10 @@ export const MainSection = ({
feature: featureYearInReview,
shouldEvaluate: isLoggedIn,
});
+ const { value: showGameCenter } = useConditionalFeature({
+ feature: questsFeature,
+ shouldEvaluate: isLoggedIn,
+ });
const menuItems: SidebarMenuItem[] = useMemo(() => {
// this path can be opened on extension so it purposly
@@ -59,7 +65,7 @@ export const MainSection = ({
action: () =>
onNavTabClick?.(isCustomDefaultFeed ? SharedFeedPage.MyFeed : '/'),
icon: () => (
-
+
),
}
: {
@@ -87,6 +93,18 @@ export const MainSection = ({
}
: undefined;
+ const gameCenter = showGameCenter
+ ? {
+ icon: (active: boolean) => (
+ } />
+ ),
+ title: 'Game Center',
+ path: `${webappUrl}game-center`,
+ isForcedLink: true,
+ requiresLogin: true,
+ }
+ : undefined;
+
const yearInReview = showYearInReview
? {
icon: () => } />,
@@ -98,54 +116,58 @@ export const MainSection = ({
}
: undefined;
- return [
- myFeed,
- {
- title: 'Following',
- // this path can be opened on extension so it purposly
- // is not using webappUrl so it gets selected
- path: '/following',
- action: () => onNavTabClick?.(OtherFeedPage.Following),
- requiresLogin: true,
- icon: (active: boolean) => (
- } />
- ),
- },
- {
- icon: (active: boolean) => (
- } />
- ),
- title: 'Explore',
- path: '/posts',
- action: () => onNavTabClick?.(OtherFeedPage.Explore),
- },
- {
- icon: (active: boolean) => (
- } />
- ),
- title: 'History',
- path: `${webappUrl}history`,
- isForcedLink: true,
- requiresLogin: true,
- },
- {
- icon: (active: boolean) => (
- } />
- ),
- title: 'Agentic Hub',
- path: `${webappUrl}agents`,
- isForcedLink: true,
- requiresLogin: true,
- },
- yearInReview,
- plusButton,
- ].filter(Boolean);
+ return (
+ [
+ myFeed,
+ {
+ title: 'Following',
+ // this path can be opened on extension so it purposly
+ // is not using webappUrl so it gets selected
+ path: '/following',
+ action: () => onNavTabClick?.(OtherFeedPage.Following),
+ requiresLogin: true,
+ icon: (active: boolean) => (
+ } />
+ ),
+ },
+ {
+ icon: (active: boolean) => (
+ } />
+ ),
+ title: 'Explore',
+ path: '/posts',
+ action: () => onNavTabClick?.(OtherFeedPage.Explore),
+ },
+ {
+ icon: (active: boolean) => (
+ } />
+ ),
+ title: 'History',
+ path: `${webappUrl}history`,
+ isForcedLink: true,
+ requiresLogin: true,
+ },
+ {
+ icon: (active: boolean) => (
+ } />
+ ),
+ title: 'Agentic Hub',
+ path: `${webappUrl}agents`,
+ isForcedLink: true,
+ requiresLogin: true,
+ },
+ gameCenter,
+ yearInReview,
+ plusButton,
+ ] as (SidebarMenuItem | undefined)[]
+ ).filter((item): item is SidebarMenuItem => !!item);
}, [
ctaCopy,
isCustomDefaultFeed,
isLoggedIn,
isPlus,
onNavTabClick,
+ showGameCenter,
showYearInReview,
user,
]);