Skip to content

Commit bc16b42

Browse files
committed
feat: add tour components to App.tsx and fix stylings
1 parent a9f21bd commit bc16b42

File tree

5 files changed

+130
-96
lines changed

5 files changed

+130
-96
lines changed

src/frontend/App.tsx

+103-95
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ import { QuestsPage } from './screens/Quests'
4141
import { NavigateListener } from './NavigateListener'
4242
import G7Webview from './screens/G7Webview'
4343
import CardPrivacyPolicy from './screens/Onboarding/analytics/CardPrivacyPolicy'
44+
// Import the TourProvider
45+
import { TourProvider } from './components/TourGuide/TourContext'
4446

4547
function App() {
4648
const { sidebarCollapsed, isSettingsModalOpen, connectivity } =
@@ -50,106 +52,112 @@ function App() {
5052

5153
return (
5254
<div className={classNames('App', { collapsed: sidebarCollapsed })}>
53-
<HashRouter>
54-
<OfflineMessage />
55-
<TopNavBar />
56-
<Sidebar />
57-
<main className="content">
58-
<CardPrivacyPolicy />
59-
<QaAuthHandler />
60-
<NavigateListener />
61-
<ExtensionHandler />
62-
<ExtensionManager />
63-
<DialogHandler />
64-
<ExternalLinkDialog />
65-
<AuthModal />
66-
<EmailSubscriptionModal />
67-
<StoreNavHandler />
68-
{isSettingsModalOpen.gameInfo && (
69-
<SettingsModal
70-
gameInfo={isSettingsModalOpen.gameInfo}
71-
type={isSettingsModalOpen.type}
72-
/>
73-
)}
74-
<Routes>
75-
<Route
76-
path="/"
77-
element={<Navigate replace to={firstDestination} />}
78-
/>
79-
<Route path="/library" element={<Library />} />
80-
<Route
81-
path="/achievements"
82-
element={
83-
<AchievementsLayout>
84-
<Outlet />
85-
</AchievementsLayout>
86-
}
87-
>
88-
<Route index element={<Achievements />} />
55+
{/* Wrap the entire app with the TourProvider */}
56+
<TourProvider>
57+
<HashRouter>
58+
<OfflineMessage />
59+
<TopNavBar />
60+
<Sidebar />
61+
<main className="content">
62+
<CardPrivacyPolicy />
63+
<QaAuthHandler />
64+
<NavigateListener />
65+
<ExtensionHandler />
66+
<ExtensionManager />
67+
<DialogHandler />
68+
<ExternalLinkDialog />
69+
<AuthModal />
70+
<EmailSubscriptionModal />
71+
<StoreNavHandler />
72+
{isSettingsModalOpen.gameInfo && (
73+
<SettingsModal
74+
gameInfo={isSettingsModalOpen.gameInfo}
75+
type={isSettingsModalOpen.type}
76+
/>
77+
)}
78+
<Routes>
8979
<Route
90-
path="/achievements/:id"
91-
element={<GameAchievementDetails />}
80+
path="/"
81+
element={<Navigate replace to={firstDestination} />}
9282
/>
93-
</Route>
94-
<Route path="login" element={<Login />} />
95-
<Route
96-
path="hyperplaystore"
97-
element={<WebView key="hyperplaystore" />}
98-
/>
99-
<Route path="epicstore" element={<WebView key="epicstore" />} />
100-
<Route path="gogstore" element={<WebView key="gogstore" />} />
101-
<Route path="docs" element={<WebView key="docs" />} />
102-
<Route path="metamaskHome" element={<MetaMaskHome />} />
103-
<Route
104-
path="metamaskSnaps"
105-
element={<WebView key="metamaskSnaps" />}
106-
/>
107-
<Route path="game7Portal" element={<G7Webview />} />
108-
<Route path="metamaskPortfolio" element={<MetaMaskPortfolio />}>
109-
<Route path=":page" element={<MetaMaskPortfolio />} />
110-
</Route>
111-
<Route path="/gamepage">
112-
<Route path=":runner">
113-
<Route path=":appName" element={<GamePage />} />
83+
<Route path="/library" element={<Library />} />
84+
<Route
85+
path="/achievements"
86+
element={
87+
<AchievementsLayout>
88+
<Outlet />
89+
</AchievementsLayout>
90+
}
91+
>
92+
<Route index element={<Achievements />} />
93+
<Route
94+
path="/achievements/:id"
95+
element={<GameAchievementDetails />}
96+
/>
97+
</Route>
98+
<Route path="login" element={<Login />} />
99+
<Route
100+
path="hyperplaystore"
101+
element={<WebView key="hyperplaystore" />}
102+
/>
103+
<Route path="epicstore" element={<WebView key="epicstore" />} />
104+
<Route path="gogstore" element={<WebView key="gogstore" />} />
105+
<Route path="docs" element={<WebView key="docs" />} />
106+
<Route path="metamaskHome" element={<MetaMaskHome />} />
107+
<Route
108+
path="metamaskSnaps"
109+
element={<WebView key="metamaskSnaps" />}
110+
/>
111+
<Route path="game7Portal" element={<G7Webview />} />
112+
<Route path="metamaskPortfolio" element={<MetaMaskPortfolio />}>
113+
<Route path=":page" element={<MetaMaskPortfolio />} />
114+
</Route>
115+
<Route path="/gamepage">
116+
<Route path=":runner">
117+
<Route path=":appName" element={<GamePage />} />
118+
</Route>
119+
</Route>
120+
<Route
121+
path="/store-page"
122+
element={<WebView key="store-page" />}
123+
/>
124+
<Route path="loginweb">
125+
<Route path=":runner" element={<WebView key="loginweb" />} />
114126
</Route>
115-
</Route>
116-
<Route path="/store-page" element={<WebView key="store-page" />} />
117-
<Route path="loginweb">
118-
<Route path=":runner" element={<WebView key="loginweb" />} />
119-
</Route>
120-
<Route path="settings">
121-
<Route path=":runner">
122-
<Route path=":appName">
123-
<Route path=":type" element={<Settings />} />
127+
<Route path="settings">
128+
<Route path=":runner">
129+
<Route path=":appName">
130+
<Route path=":type" element={<Settings />} />
131+
</Route>
124132
</Route>
125133
</Route>
126-
</Route>
127-
<Route path="/download-manager" element={<DownloadManager />} />
128-
<Route path="/quests" element={<QuestsPage />}>
129-
<Route path=":questId" element={<QuestsPage />} />
130-
</Route>
131-
</Routes>
132-
</main>
133-
<div className="controller">
134-
<ControllerHints />
135-
<div className="simple-keyboard"></div>
136-
</div>
137-
<OnboardingStoreController />
138-
{onboardingStore.isOnboardingOpen && (
139-
<Onboarding
140-
disableOnboarding={(disableReason: WalletOnboardCloseReason) => {
141-
if (disableReason === 'skipped') {
142-
window.api.trackEvent({ event: 'Onboarding Skipped' })
143-
}
144-
onboardingStore.closeOnboarding()
145-
}}
146-
/>
147-
)}
148-
</HashRouter>
149-
<TransactionNotification />
150-
<DownloadToastManager />
151-
<DeviceStateController />
152-
<UpdateModalController />
134+
<Route path="/download-manager" element={<DownloadManager />} />
135+
<Route path="/quests" element={<QuestsPage />}>
136+
<Route path=":questId" element={<QuestsPage />} />
137+
</Route>
138+
</Routes>
139+
</main>
140+
<div className="controller">
141+
<ControllerHints />
142+
<div className="simple-keyboard"></div>
143+
</div>
144+
<OnboardingStoreController />
145+
{onboardingStore.isOnboardingOpen && (
146+
<Onboarding
147+
disableOnboarding={(disableReason: WalletOnboardCloseReason) => {
148+
if (disableReason === 'skipped') {
149+
window.api.trackEvent({ event: 'Onboarding Skipped' })
150+
}
151+
onboardingStore.closeOnboarding()
152+
}}
153+
/>
154+
)}
155+
</HashRouter>
156+
<TransactionNotification />
157+
<DownloadToastManager />
158+
<DeviceStateController />
159+
<UpdateModalController />
160+
</TourProvider>
153161
</div>
154162
)
155163
}

src/frontend/screens/Library/components/GamesList/index.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ const GamesList = observer(
8383
gameListLayout: layout === 'list',
8484
firstLane: isFirstLane
8585
})}
86+
data-tour="games-list"
8687
>
8788
{layout === 'list' && (
8889
<div className="gameListHeader">

src/frontend/screens/Library/components/LibraryTopBar/index.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export const LibraryTopBar = observer(
4949
libraryState.category = val as Category
5050
}
5151
}}
52+
data-tour="filters"
5253
defaultValue={category}
5354
classNames={getTabsClassNames(
5455
{ list: styles.tabsList },

src/frontend/screens/Library/index.module.scss

+5
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,8 @@
7070
justify-content: center;
7171
align-items: center;
7272
}
73+
74+
.tourButton {
75+
padding: var(--space-xs);
76+
margin-left: var(--space-md-fixed);
77+
}

src/frontend/screens/Library/index.tsx

+20-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ import libraryState from '../../state/libraryState'
2626
import { observer } from 'mobx-react-lite'
2727
import storeAuthState from 'frontend/state/storeAuthState'
2828
import SteamInstallButton from './components/SteamInstall/SteamInstallButton'
29+
import { useTourGuide } from 'frontend/components/TourGuide/TourContext'
30+
import TourGuide from 'frontend/components/TourGuide/TourGuide'
31+
import TourTriggerButton from 'frontend/components/TourGuide/TourTriggerButton'
2932

3033
const storage = window.localStorage
3134

@@ -40,6 +43,7 @@ export default observer(function Library(): JSX.Element {
4043
const { layout, epic, gog, platform, connectivity } =
4144
useContext(ContextProvider)
4245
const { t } = useTranslation()
46+
const { isTourCompleted, activateLibraryTour } = useTourGuide()
4347

4448
const isOffline = connectivity.status !== 'online'
4549

@@ -97,6 +101,16 @@ export default observer(function Library(): JSX.Element {
97101
useEffect(() => {
98102
window.api.trackScreen('Library')
99103
libraryState.selectedFilter = filters[0]
104+
105+
// Start library tour if it hasn't been completed
106+
if (!isTourCompleted('library')) {
107+
// Delay to allow components to fully render
108+
const timer = setTimeout(() => {
109+
activateLibraryTour()
110+
}, 1000)
111+
return () => clearTimeout(timer)
112+
}
113+
return
100114
}, [])
101115

102116
const backToTop = () => {
@@ -226,14 +240,15 @@ export default observer(function Library(): JSX.Element {
226240
<>
227241
<Background style={{ position: 'absolute' }}></Background>
228242
<div className="Library contentContainer" ref={listing}>
229-
<div className={styles.libraryTopHeader}>
243+
<div data-tour="library-top-header" className={styles.libraryTopHeader}>
230244
<h3>{t('library.label', 'Library')}</h3>
231245
<span className={`${styles.numberOfgames} title`}>
232246
{numberOfGames}
233247
</span>
234248
<Button
235249
className={styles.refreshButton}
236250
type="tertiary"
251+
data-tour="refresh"
237252
title={t('generic.library.refresh', 'Refresh Library')}
238253
disabled={isOffline}
239254
onClick={async () =>
@@ -252,12 +267,14 @@ export default observer(function Library(): JSX.Element {
252267
</Button>
253268
<Button
254269
type="tertiary"
270+
data-tour="add-game"
255271
onClick={() => handleModal('', 'sideload', null)}
256272
leftIcon={<FontAwesomeIcon icon={faPlus} height={14} width={14} />}
257273
>
258274
{t('add_game', 'Add Game')}
259275
</Button>
260276
{isMac ? <SteamInstallButton /> : null}
277+
<TourTriggerButton className={styles.tourButton} />
261278
</div>
262279
<LibraryTopBar
263280
filters={filters}
@@ -272,6 +289,7 @@ export default observer(function Library(): JSX.Element {
272289
<span id="top" />
273290
{showRecentGames && (
274291
<RecentlyPlayed
292+
data-tour="recently-played"
275293
handleModal={handleModal}
276294
onlyInstalled={libraryState.libraryTopSection.endsWith(
277295
'installed'
@@ -332,6 +350,7 @@ export default observer(function Library(): JSX.Element {
332350
/>
333351
)}
334352
</div>
353+
<TourGuide />
335354
</>
336355
)
337356
})

0 commit comments

Comments
 (0)