11import { Box } from "@mui/material" ;
2- import { useState } from "react" ;
2+ import { useRef , useState } from "react" ;
33import TitleBar from "./components/TitleBar" ;
44import { useAppInitialization } from "./hooks/useAppInitialization" ;
55import { useInstalledApps } from "./hooks/useInstalledApps" ;
@@ -11,12 +11,22 @@ import { Welcome } from "./pages/welcome/Welcome";
1111import type { AppStream } from "./types" ;
1212import "./App.css" ;
1313
14+ type ViewType = "home" | "appDetails" | "category" | "myApps" ;
15+
16+ interface NavigationState {
17+ view : ViewType ;
18+ app ?: AppStream ;
19+ category ?: string ;
20+ scrollPosition ?: number ;
21+ }
22+
1423function App ( ) {
15- const [ selectedApp , setSelectedApp ] = useState < AppStream | null > ( null ) ;
16- const [ selectedCategory , setSelectedCategory ] = useState < string | null > ( null ) ;
17- const [ showMyApps , setShowMyApps ] = useState ( false ) ;
24+ const [ navigationStack , setNavigationStack ] = useState < NavigationState [ ] > ( [
25+ { view : "home" } ,
26+ ] ) ;
1827 const [ showWelcome , setShowWelcome ] = useState ( true ) ;
1928 const { isFirstLaunch, isInitializing, error } = useAppInitialization ( ) ;
29+ const scrollContainerRef = useRef < HTMLDivElement > ( null ) ;
2030
2131 // Load installed apps on startup (non-blocking)
2232 // This also loads available updates after installed apps are loaded
@@ -26,6 +36,62 @@ function App() {
2636 setShowWelcome ( false ) ;
2737 } ;
2838
39+ const currentState = navigationStack [ navigationStack . length - 1 ] ;
40+
41+ const saveScrollPosition = ( ) => {
42+ if ( scrollContainerRef . current ) {
43+ const scrollPosition = scrollContainerRef . current . scrollTop ;
44+ setNavigationStack ( ( prev ) => {
45+ const newStack = [ ...prev ] ;
46+ newStack [ newStack . length - 1 ] = {
47+ ...newStack [ newStack . length - 1 ] ,
48+ scrollPosition,
49+ } ;
50+ return newStack ;
51+ } ) ;
52+ }
53+ } ;
54+
55+ const restoreScrollPosition = ( position ?: number ) => {
56+ if ( scrollContainerRef . current && position !== undefined ) {
57+ scrollContainerRef . current . scrollTop = position ;
58+ }
59+ } ;
60+
61+ const navigateTo = ( state : NavigationState ) => {
62+ saveScrollPosition ( ) ;
63+ setNavigationStack ( ( prev ) => [ ...prev , state ] ) ;
64+ // Reset scroll to top for new views
65+ if ( scrollContainerRef . current ) {
66+ scrollContainerRef . current . scrollTop = 0 ;
67+ }
68+ } ;
69+
70+ const navigateBack = ( ) => {
71+ if ( navigationStack . length > 1 ) {
72+ setNavigationStack ( ( prev ) => {
73+ const newStack = prev . slice ( 0 , - 1 ) ;
74+ // Restore scroll position after state update
75+ setTimeout ( ( ) => {
76+ restoreScrollPosition ( newStack [ newStack . length - 1 ] . scrollPosition ) ;
77+ } , 0 ) ;
78+ return newStack ;
79+ } ) ;
80+ }
81+ } ;
82+
83+ const handleAppSelect = ( app : AppStream ) => {
84+ navigateTo ( { view : "appDetails" , app } ) ;
85+ } ;
86+
87+ const handleCategorySelect = ( categoryId : string ) => {
88+ navigateTo ( { view : "category" , category : categoryId } ) ;
89+ } ;
90+
91+ const handleMyAppsClick = ( ) => {
92+ navigateTo ( { view : "myApps" } ) ;
93+ } ;
94+
2995 // Show loading state while initializing
3096 if ( isInitializing ) {
3197 return (
@@ -97,6 +163,7 @@ function App() {
97163 < >
98164 < TitleBar />
99165 < Box
166+ ref = { scrollContainerRef }
100167 sx = { {
101168 marginTop : "40px" ,
102169 height : "calc(100vh - 40px)" ,
@@ -105,30 +172,25 @@ function App() {
105172 borderTop : "none" ,
106173 } }
107174 >
108- { selectedApp && (
109- < AppDetails
110- app = { selectedApp }
111- onBack = { ( ) => {
112- setSelectedApp ( null ) ;
113- } }
114- />
175+ { currentState . view === "appDetails" && currentState . app && (
176+ < AppDetails app = { currentState . app } onBack = { navigateBack } />
115177 ) }
116178
117- { selectedCategory && (
179+ { currentState . view === "category" && currentState . category && (
118180 < CategoryApps
119- categoryId = { selectedCategory }
120- onBack = { ( ) => setSelectedCategory ( null ) }
121- onAppSelect = { setSelectedApp }
181+ categoryId = { currentState . category }
182+ onBack = { navigateBack }
183+ onAppSelect = { handleAppSelect }
122184 />
123185 ) }
124186
125- { showMyApps && < MyApps onBack = { ( ) => setShowMyApps ( false ) } /> }
187+ { currentState . view === "myApps" && < MyApps onBack = { navigateBack } /> }
126188
127- { ! selectedApp && ! selectedCategory && ! showMyApps && (
189+ { currentState . view === "home" && (
128190 < Home
129- onAppSelect = { setSelectedApp }
130- onCategorySelect = { setSelectedCategory }
131- onMyAppsClick = { ( ) => setShowMyApps ( true ) }
191+ onAppSelect = { handleAppSelect }
192+ onCategorySelect = { handleCategorySelect }
193+ onMyAppsClick = { handleMyAppsClick }
132194 />
133195 ) }
134196 </ Box >
0 commit comments