Skip to content

Commit cea73d4

Browse files
feat: add Game Center entry points to desktop and mobile sidebars (#5812)
1 parent d3a6488 commit cea73d4

File tree

7 files changed

+134
-77
lines changed

7 files changed

+134
-77
lines changed

packages/shared/src/components/ProfileMenu/sections/MainSection.tsx

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import type { ReactElement } from 'react';
33

44
import { ProfileSection } from '../ProfileSection';
5+
import type { ProfileSectionItemProps } from '../ProfileSectionItem';
56
import {
67
AnalyticsIcon,
78
CoinIcon,
@@ -17,35 +18,37 @@ export const MainSection = (): ReactElement => {
1718
const hasAccessToCores = useHasAccessToCores();
1819
const { user } = useAuthContext();
1920

20-
return (
21-
<ProfileSection
22-
items={[
23-
{
24-
title: 'Your profile',
25-
href: `${webappUrl}${user.username}`,
26-
icon: UserIcon,
27-
},
28-
hasAccessToCores && {
29-
title: 'Core wallet',
30-
href: walletUrl,
31-
icon: CoinIcon,
32-
},
33-
{
34-
title: 'Achievements',
35-
href: `${webappUrl}${user.username}/achievements`,
36-
icon: MedalBadgeIcon,
37-
},
38-
{
39-
title: 'DevCard',
40-
href: `${settingsUrl}/customization/devcard`,
41-
icon: DevCardIcon,
42-
},
43-
{
44-
title: 'Analytics',
45-
href: `${webappUrl}analytics`,
46-
icon: AnalyticsIcon,
47-
},
48-
].filter(Boolean)}
49-
/>
50-
);
21+
const items: ProfileSectionItemProps[] = [
22+
{
23+
title: 'Your profile',
24+
href: `${webappUrl}${user?.username}`,
25+
icon: UserIcon,
26+
},
27+
...(hasAccessToCores
28+
? [
29+
{
30+
title: 'Core wallet',
31+
href: walletUrl,
32+
icon: CoinIcon,
33+
} satisfies ProfileSectionItemProps,
34+
]
35+
: []),
36+
{
37+
title: 'Achievements',
38+
href: `${webappUrl}${user?.username}/achievements`,
39+
icon: MedalBadgeIcon,
40+
},
41+
{
42+
title: 'DevCard',
43+
href: `${settingsUrl}/customization/devcard`,
44+
icon: DevCardIcon,
45+
},
46+
{
47+
title: 'Analytics',
48+
href: `${webappUrl}analytics`,
49+
icon: AnalyticsIcon,
50+
},
51+
];
52+
53+
return <ProfileSection items={items} />;
5154
};
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { ReactElement } from 'react';
2+
import React from 'react';
3+
import type { IconProps } from '../../Icon';
4+
import Icon from '../../Icon';
5+
import OutlinedIcon from './outlined.svg';
6+
import FilledIcon from './filled.svg';
7+
8+
export const JoystickIcon = (props: IconProps): ReactElement => (
9+
<Icon {...props} IconPrimary={OutlinedIcon} IconSecondary={FilledIcon} />
10+
);
Lines changed: 4 additions & 0 deletions
Loading

packages/shared/src/components/icons/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export * from './Italic';
8080
export * from './JetBrains';
8181
export * from './Job';
8282
export * from './JobStatus';
83+
export * from './Joystick';
8384
export * from './Kaggle';
8485
export * from './Key';
8586
export * from './Label';

packages/shared/src/components/profile/ProfileSettingsMenu.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
TourIcon,
3535
FeatherIcon,
3636
GiftIcon,
37+
JoystickIcon,
3738
} from '../icons';
3839
import { NavDrawer } from '../drawers/NavDrawer';
3940
import {
@@ -188,6 +189,11 @@ const useAccountPageItems = ({ onClose }: { onClose?: () => void } = {}) => {
188189
onClose?.();
189190
},
190191
},
192+
gameCenter: {
193+
title: 'Game Center',
194+
icon: JoystickIcon,
195+
href: `${webappUrl}game-center`,
196+
},
191197
trackAchievement: {
192198
title: 'Track achievement',
193199
icon: PinIcon,
@@ -438,7 +444,7 @@ export const InnerProfileSettingsMenu = ({
438444
<ProfileSection
439445
key={key}
440446
withSeparator={!lastItem}
441-
title={menuItem.title}
447+
title={menuItem.title ?? undefined}
442448
items={Object.entries(menuItem.items)
443449
.filter(([itemKey, item]) => {
444450
if (item.href === walletUrl && !hasAccessToCores) {
@@ -459,6 +465,13 @@ export const InnerProfileSettingsMenu = ({
459465
return false;
460466
}
461467

468+
if (
469+
itemKey === 'gameCenter' &&
470+
isQuestsFeatureEnabled !== true
471+
) {
472+
return false;
473+
}
474+
462475
return true;
463476
})
464477
.map(([, item]: [string, ProfileSectionItemProps]) => {
@@ -491,15 +504,15 @@ export function ProfileSettingsMenuMobile({
491504
shouldKeepOpen={shouldKeepOpen}
492505
drawerProps={{
493506
isOpen,
494-
onClose,
507+
onClose: onClose ?? (() => {}),
495508
}}
496509
>
497510
<InnerProfileSettingsMenu className="p-4" onClose={onClose} />
498511
</NavDrawer>
499512
);
500513
}
501514

502-
export function ProfileSettingsMenuDesktop(): ReactElement {
515+
export function ProfileSettingsMenuDesktop(): ReactElement | null {
503516
const { user } = useAuthContext();
504517
const featureTheme = useFeatureTheme();
505518

packages/shared/src/components/sidebar/sections/MainSection.tsx

Lines changed: 65 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
EyeIcon,
99
HomeIcon,
1010
HotIcon,
11+
JoystickIcon,
1112
SquadIcon,
1213
TerminalIcon,
1314
YearInReviewIcon,
@@ -24,6 +25,7 @@ import { useConditionalFeature } from '../../../hooks';
2425
import {
2526
featurePlusCtaCopy,
2627
featureYearInReview,
28+
questsFeature,
2729
} from '../../../lib/featureManagement';
2830

2931
export const MainSection = ({
@@ -42,6 +44,10 @@ export const MainSection = ({
4244
feature: featureYearInReview,
4345
shouldEvaluate: isLoggedIn,
4446
});
47+
const { value: showGameCenter } = useConditionalFeature({
48+
feature: questsFeature,
49+
shouldEvaluate: isLoggedIn,
50+
});
4551

4652
const menuItems: SidebarMenuItem[] = useMemo(() => {
4753
// this path can be opened on extension so it purposly
@@ -59,7 +65,7 @@ export const MainSection = ({
5965
action: () =>
6066
onNavTabClick?.(isCustomDefaultFeed ? SharedFeedPage.MyFeed : '/'),
6167
icon: () => (
62-
<ProfilePicture size={ProfileImageSize.XSmall} user={user} />
68+
<ProfilePicture size={ProfileImageSize.XSmall} user={user!} />
6369
),
6470
}
6571
: {
@@ -87,6 +93,18 @@ export const MainSection = ({
8793
}
8894
: undefined;
8995

96+
const gameCenter = showGameCenter
97+
? {
98+
icon: (active: boolean) => (
99+
<ListIcon Icon={() => <JoystickIcon secondary={active} />} />
100+
),
101+
title: 'Game Center',
102+
path: `${webappUrl}game-center`,
103+
isForcedLink: true,
104+
requiresLogin: true,
105+
}
106+
: undefined;
107+
90108
const yearInReview = showYearInReview
91109
? {
92110
icon: () => <ListIcon Icon={() => <YearInReviewIcon />} />,
@@ -98,54 +116,58 @@ export const MainSection = ({
98116
}
99117
: undefined;
100118

101-
return [
102-
myFeed,
103-
{
104-
title: 'Following',
105-
// this path can be opened on extension so it purposly
106-
// is not using webappUrl so it gets selected
107-
path: '/following',
108-
action: () => onNavTabClick?.(OtherFeedPage.Following),
109-
requiresLogin: true,
110-
icon: (active: boolean) => (
111-
<ListIcon Icon={() => <SquadIcon secondary={active} />} />
112-
),
113-
},
114-
{
115-
icon: (active: boolean) => (
116-
<ListIcon Icon={() => <HotIcon secondary={active} />} />
117-
),
118-
title: 'Explore',
119-
path: '/posts',
120-
action: () => onNavTabClick?.(OtherFeedPage.Explore),
121-
},
122-
{
123-
icon: (active: boolean) => (
124-
<ListIcon Icon={() => <EyeIcon secondary={active} />} />
125-
),
126-
title: 'History',
127-
path: `${webappUrl}history`,
128-
isForcedLink: true,
129-
requiresLogin: true,
130-
},
131-
{
132-
icon: (active: boolean) => (
133-
<ListIcon Icon={() => <TerminalIcon secondary={active} />} />
134-
),
135-
title: 'Agentic Hub',
136-
path: `${webappUrl}agents`,
137-
isForcedLink: true,
138-
requiresLogin: true,
139-
},
140-
yearInReview,
141-
plusButton,
142-
].filter(Boolean);
119+
return (
120+
[
121+
myFeed,
122+
{
123+
title: 'Following',
124+
// this path can be opened on extension so it purposly
125+
// is not using webappUrl so it gets selected
126+
path: '/following',
127+
action: () => onNavTabClick?.(OtherFeedPage.Following),
128+
requiresLogin: true,
129+
icon: (active: boolean) => (
130+
<ListIcon Icon={() => <SquadIcon secondary={active} />} />
131+
),
132+
},
133+
{
134+
icon: (active: boolean) => (
135+
<ListIcon Icon={() => <HotIcon secondary={active} />} />
136+
),
137+
title: 'Explore',
138+
path: '/posts',
139+
action: () => onNavTabClick?.(OtherFeedPage.Explore),
140+
},
141+
{
142+
icon: (active: boolean) => (
143+
<ListIcon Icon={() => <EyeIcon secondary={active} />} />
144+
),
145+
title: 'History',
146+
path: `${webappUrl}history`,
147+
isForcedLink: true,
148+
requiresLogin: true,
149+
},
150+
{
151+
icon: (active: boolean) => (
152+
<ListIcon Icon={() => <TerminalIcon secondary={active} />} />
153+
),
154+
title: 'Agentic Hub',
155+
path: `${webappUrl}agents`,
156+
isForcedLink: true,
157+
requiresLogin: true,
158+
},
159+
gameCenter,
160+
yearInReview,
161+
plusButton,
162+
] as (SidebarMenuItem | undefined)[]
163+
).filter((item): item is SidebarMenuItem => !!item);
143164
}, [
144165
ctaCopy,
145166
isCustomDefaultFeed,
146167
isLoggedIn,
147168
isPlus,
148169
onNavTabClick,
170+
showGameCenter,
149171
showYearInReview,
150172
user,
151173
]);

0 commit comments

Comments
 (0)