@@ -28,58 +28,15 @@ import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
2828import Background from "./components/canvas/background" ;
2929import WebSocketStatus from "./components/canvas/ws-status" ;
3030import Subtitle from "./components/canvas/subtitle" ;
31+ import { ModeProvider , useMode } from "./context/mode-context" ;
3132
32- function App ( ) : JSX . Element {
33+ function AppContent ( ) : JSX . Element {
3334 const [ showSidebar , setShowSidebar ] = useState ( true ) ;
3435 const [ isFooterCollapsed , setIsFooterCollapsed ] = useState ( false ) ;
35- const [ mode , setMode ] = useState ( "window" ) ;
36+ const { mode } = useMode ( ) ;
3637 const isElectron = window . api !== undefined ;
3738 const live2dContainerRef = useRef < HTMLDivElement > ( null ) ;
3839
39- useEffect ( ( ) => {
40- if ( isElectron && window . electron ) {
41- // Added check for window.electron
42- const handlePreModeChange = ( _event : any , newMode : any ) => {
43- // Added types
44- requestAnimationFrame ( ( ) => {
45- requestAnimationFrame ( ( ) => {
46- window . electron ?. ipcRenderer . send (
47- "renderer-ready-for-mode-change" ,
48- newMode
49- ) ;
50- } ) ;
51- } ) ;
52- } ;
53- const handleModeChanged = ( _event : any , newMode : any ) => {
54- // Added types
55- setMode ( newMode ) ;
56- requestAnimationFrame ( ( ) => {
57- requestAnimationFrame ( ( ) => {
58- window . electron ?. ipcRenderer . send ( "mode-change-rendered" ) ;
59- } ) ;
60- } ) ;
61- } ;
62-
63- window . electron . ipcRenderer . on ( "pre-mode-changed" , handlePreModeChange ) ;
64- window . electron . ipcRenderer . on ( "mode-changed" , handleModeChanged ) ;
65-
66- return ( ) => {
67- // Check again before removing listeners
68- if ( window . electron ) {
69- window . electron . ipcRenderer . removeListener (
70- "pre-mode-changed" ,
71- handlePreModeChange
72- ) ;
73- window . electron . ipcRenderer . removeListener (
74- "mode-changed" ,
75- handleModeChanged
76- ) ;
77- }
78- } ;
79- }
80- return undefined ;
81- } , [ isElectron ] ) ;
82-
8340 useEffect ( ( ) => {
8441 const handleResize = ( ) => {
8542 const vh = window . innerHeight * 0.01 ;
@@ -90,34 +47,129 @@ function App(): JSX.Element {
9047 return ( ) => window . removeEventListener ( "resize" , handleResize ) ;
9148 } , [ ] ) ;
9249
50+
51+ document . documentElement . style . overflow = 'hidden' ;
52+ document . body . style . overflow = 'hidden' ;
53+ document . documentElement . style . height = '100%' ;
54+ document . body . style . height = '100%' ;
55+ document . documentElement . style . position = 'fixed' ;
56+ document . body . style . position = 'fixed' ;
57+ document . documentElement . style . width = '100%' ;
58+ document . body . style . width = '100%' ;
59+
60+ // Define base style properties shared across modes/breakpoints
9361 const live2dBaseStyle = {
9462 position : "absolute" as const ,
9563 overflow : "hidden" ,
9664 transition : "all 0.3s ease-in-out" , // Optional transition
65+ pointerEvents : "auto" as const ,
9766 } ;
9867
99- const live2dWindowStyle = {
68+ // Define styles specifically for the "window" mode, using responsive syntax
69+ const getResponsiveLive2DWindowStyle = ( sidebarVisible : boolean ) => ( {
10070 ...live2dBaseStyle ,
10171 top : isElectron ? "30px" : "0px" ,
102- left : showSidebar ? "440px" : "24px" ,
103- width : `calc(100% - ${ showSidebar ? "440px" : "24px" } )` ,
10472 height : `calc(100% - ${ isElectron ? "30px" : "0px" } )` ,
105- zIndex : 5 ,
106- pointerEvents : "auto" as const ,
107- } ;
73+ zIndex : 5 , // Ensure it's layered correctly below UI but above background
74+ left : {
75+ base : "0px" , // Column layout (base): Start from left edge
76+ md : sidebarVisible ? "440px" : "24px" , // Row layout (md+): Offset by sidebar width
77+ } ,
78+ width : {
79+ base : "100%" , // Column layout (base): Full width
80+ md : `calc(100% - ${ sidebarVisible ? "440px" : "24px" } )` , // Row layout (md+): Adjust width based on sidebar
81+ } ,
82+ } ) ;
10883
84+ // Define styles specifically for the "pet" mode
10985 const live2dPetStyle = {
11086 ...live2dBaseStyle ,
111- top : 0 ,
87+ top : 0 , // Override position for pet mode
11288 left : 0 ,
113- width : "100vw" ,
89+ width : "100vw" , // Full viewport
11490 height : "100vh" ,
115- zIndex : 15 ,
116- pointerEvents : "auto" as const ,
91+ zIndex : 15 , // Higher zIndex for pet mode overlay
11792 } ;
11893
94+ return (
95+ < >
96+ < Box
97+ ref = { live2dContainerRef }
98+ // Apply styles conditionally based on mode
99+ // Use the function to get dynamic responsive styles for window mode
100+ { ...( mode === "window"
101+ ? getResponsiveLive2DWindowStyle ( showSidebar )
102+ : live2dPetStyle ) }
103+ >
104+ < Live2D />
105+ </ Box >
106+
107+ { /* Conditional Rendering of Window UI */ }
108+ { mode === "window" && (
109+ < >
110+ { isElectron && < TitleBar /> }
111+ { /* Apply styles by spreading */ }
112+ < Flex { ...layoutStyles . appContainer } >
113+ < Box
114+ { ...layoutStyles . sidebar }
115+ { ...( ! showSidebar && { width : "24px" } ) }
116+ >
117+ < Sidebar
118+ isCollapsed = { ! showSidebar }
119+ onToggle = { ( ) => setShowSidebar ( ! showSidebar ) }
120+ />
121+ </ Box >
122+ < Box { ...layoutStyles . mainContent } >
123+ < Background />
124+ < Box position = "absolute" top = "20px" left = "20px" zIndex = { 10 } >
125+ < WebSocketStatus />
126+ </ Box >
127+ < Box
128+ position = "absolute"
129+ bottom = { isFooterCollapsed ? "39px" : "135px" }
130+ left = "50%"
131+ transform = "translateX(-50%)"
132+ zIndex = { 10 }
133+ width = "60%"
134+ >
135+ < Subtitle />
136+ </ Box >
137+ < Box
138+ { ...layoutStyles . footer }
139+ zIndex = { 10 }
140+ { ...( isFooterCollapsed && layoutStyles . collapsedFooter ) }
141+ >
142+ < Footer
143+ isCollapsed = { isFooterCollapsed }
144+ onToggle = { ( ) => setIsFooterCollapsed ( ! isFooterCollapsed ) }
145+ />
146+ </ Box >
147+ </ Box >
148+ </ Flex >
149+ </ >
150+ ) }
151+
152+ { /* Conditional Rendering of Pet Mode UI */ }
153+ { mode === "pet" && < InputSubtitle /> }
154+ </ >
155+ ) ;
156+ }
157+
158+ function App ( ) : JSX . Element {
119159 return (
120160 < ChakraProvider value = { defaultSystem } >
161+ { /* ModeProvider needs to wrap AppContent to provide mode to getGlobalStyles */ }
162+ < ModeProvider >
163+ < AppWithGlobalStyles />
164+ </ ModeProvider >
165+ </ ChakraProvider >
166+ ) ;
167+ }
168+
169+ // New component to access mode for global styles
170+ function AppWithGlobalStyles ( ) : JSX . Element {
171+ return (
172+ < >
121173 < CameraProvider >
122174 < ScreenCaptureProvider >
123175 < CharacterConfigProvider >
@@ -132,83 +184,7 @@ function App(): JSX.Element {
132184 < BrowserProvider >
133185 < WebSocketHandler >
134186 < Toaster />
135-
136- { /* Render Live2D Persistently with correct style props */ }
137- < Box
138- ref = { live2dContainerRef }
139- { ...( mode === "window"
140- ? live2dWindowStyle
141- : live2dPetStyle ) }
142- >
143- < Live2D
144- isPet = { mode === "pet" }
145- showSidebar = { showSidebar }
146- />
147- </ Box >
148-
149- { /* Conditional Rendering of Window UI */ }
150- { mode === "window" && (
151- < >
152- { isElectron && < TitleBar /> }
153- { /* Apply styles by spreading */ }
154- < Flex { ...layoutStyles . appContainer } >
155- < Box
156- { ...layoutStyles . sidebar }
157- { ...( ! showSidebar && { width : "24px" } ) }
158- >
159- < Sidebar
160- isCollapsed = { ! showSidebar }
161- onToggle = { ( ) =>
162- setShowSidebar ( ! showSidebar )
163- }
164- />
165- </ Box >
166- < Box { ...layoutStyles . mainContent } >
167- < Background />
168- < Box
169- position = "absolute"
170- top = "20px"
171- left = "20px"
172- zIndex = { 10 }
173- >
174- < WebSocketStatus />
175- </ Box >
176- < Box
177- position = "absolute"
178- bottom = {
179- isFooterCollapsed ? "39px" : "135px"
180- }
181- left = "50%"
182- transform = "translateX(-50%)"
183- zIndex = { 10 }
184- width = "60%"
185- >
186- < Subtitle />
187- </ Box >
188- < Box
189- { ...layoutStyles . footer }
190- zIndex = { 10 }
191- { ...( isFooterCollapsed &&
192- layoutStyles . collapsedFooter ) }
193- >
194- < Footer
195- isCollapsed = { isFooterCollapsed }
196- onToggle = { ( ) =>
197- setIsFooterCollapsed (
198- ! isFooterCollapsed
199- )
200- }
201- />
202- </ Box >
203- </ Box >
204- </ Flex >
205- </ >
206- ) }
207-
208- { /* Conditional Rendering of Pet Mode UI */ }
209- { mode === "pet" && (
210- < InputSubtitle isPet = { mode === "pet" } />
211- ) }
187+ < AppContent />
212188 </ WebSocketHandler >
213189 </ BrowserProvider >
214190 </ GroupProvider >
@@ -222,8 +198,8 @@ function App(): JSX.Element {
222198 </ CharacterConfigProvider >
223199 </ ScreenCaptureProvider >
224200 </ CameraProvider >
225- x{ " " }
226- </ ChakraProvider >
201+ </ >
227202 ) ;
228203}
204+
229205export default App ;
0 commit comments