@@ -18,57 +18,51 @@ import {
1818 getTooltipArrowStyle ,
1919 getOpenIndicatorStyle ,
2020} from './DockStyle' ;
21- import disabledOverlay from '../../media/icons/disable.png' ; // your 30%-opacity overlay image
21+ import disabledOverlay from '../../media/icons/disable.png' ;
2222
2323export default function Dock ( ) {
24- // 1) Synchronously detect portrait -mobile on first render:
24+ // 1) Portrait -mobile detection
2525 const [ isMobilePortrait , setIsMobilePortrait ] = useState ( ( ) => {
26- if ( typeof window === 'undefined' || ! window . matchMedia ) {
27- return false ;
28- }
29- return window . matchMedia (
30- '(max-width: 768px) and (orientation: portrait)'
31- ) . matches ;
26+ if ( typeof window === 'undefined' || ! window . matchMedia ) return false ;
27+ return window
28+ . matchMedia ( '(max-width: 768px) and (orientation: portrait)' )
29+ . matches ;
3230 } ) ;
33-
34- // 2) Keep it up-to-date on resize/orientation changes:
3531 useEffect ( ( ) => {
3632 if ( ! window . matchMedia ) return ;
37- const mql = window . matchMedia ( '(max-width: 768px) and (orientation: portrait)' ) ;
33+ const mql = window . matchMedia (
34+ '(max-width: 768px) and (orientation: portrait)'
35+ ) ;
3836 const handler = ( e ) => setIsMobilePortrait ( e . matches ) ;
39-
40- if ( mql . addEventListener ) {
41- mql . addEventListener ( 'change' , handler ) ;
42- } else {
43- mql . addListener ( handler ) ;
44- }
37+ mql . addEventListener
38+ ? mql . addEventListener ( 'change' , handler )
39+ : mql . addListener ( handler ) ;
4540 return ( ) => {
46- if ( mql . removeEventListener ) {
47- mql . removeEventListener ( 'change' , handler ) ;
48- } else {
49- mql . removeListener ( handler ) ;
50- }
41+ mql . removeEventListener
42+ ? mql . removeEventListener ( 'change' , handler )
43+ : mql . removeListener ( handler ) ;
5144 } ;
5245 } , [ ] ) ;
5346
54- // 3) Choose the effective config each render:
47+ // 2) Pick config
5548 const effectiveConfig = isMobilePortrait
5649 ? { ...DOCK_CONFIG , ...DOCK_CONFIG . vertical }
5750 : DOCK_CONFIG ;
5851
59- // 4) Always call the hook in the same place:
52+ // 3) Call our updated hook (no desktopId needed; dock is global)
6053 const {
6154 outerRef,
6255 iconsContainerRef,
6356 isDockVisible,
6457 paginationEnabled,
6558 isVerticalDock,
66- appsToRender,
59+ dockApps, // pinned + open
60+ appsToRender, // page slice or full
6761 scales,
6862 shouldTransition,
6963 hoveredApp,
7064 activeApp,
71- openedApps,
65+ openedApps, // array of open app IDs
7266 currentPage,
7367 totalPages,
7468 iconsPerPage,
@@ -91,10 +85,10 @@ export default function Dock() {
9185 handleMouseEnter,
9286 handleMouseMove,
9387 handleMouseLeave,
94- openApp,
88+ openApp, // opens via context
9589 handleIconMouseEnter,
9690 handleIconMouseLeave,
97- setCurrentPage, // now our animated changer
91+ setCurrentPage, // for pagination
9892 } = useDock ( {
9993 AppsContext,
10094 DOCK_CONFIG : effectiveConfig ,
@@ -103,12 +97,8 @@ export default function Dock() {
10397 useLogger,
10498 } ) ;
10599
106- // rest of your state+effects unchanged:
107-
108- const [ fadeVisible , setFadeVisible ] = useState ( isDockVisible ) ;
100+ // 4) Keyboard offset
109101 const [ toolbarOffset , setToolbarOffset ] = useState ( 0 ) ;
110-
111- // adjust for on-screen keyboard
112102 useLayoutEffect ( ( ) => {
113103 const updateOffset = ( ) => {
114104 if ( window . visualViewport ) {
@@ -125,44 +115,35 @@ export default function Dock() {
125115 } ;
126116 } , [ ] ) ;
127117
128- // fade in/out
118+ // 5) Fade in/out
119+ const [ fadeVisible , setFadeVisible ] = useState ( isDockVisible ) ;
129120 useEffect ( ( ) => {
130- let timer ;
131- if ( isDockVisible ) {
132- setFadeVisible ( true ) ;
133- } else {
134- timer = setTimeout ( ( ) => setFadeVisible ( false ) , 300 ) ;
135- }
136- return ( ) => clearTimeout ( timer ) ;
121+ let id ;
122+ if ( isDockVisible ) setFadeVisible ( true ) ;
123+ else id = setTimeout ( ( ) => setFadeVisible ( false ) , 300 ) ;
124+ return ( ) => clearTimeout ( id ) ;
137125 } , [ isDockVisible ] ) ;
138126
139- // compute outer style
127+ // 6) Compute outer style
140128 const outerStyle = {
141129 ...getOuterContainerStyle ( DOCK_POSITION , DOCK_MARGIN , isDockVisible ) ,
142130 opacity : fadeVisible ? 1 : 0 ,
143131 top : 'auto' ,
132+ ...( DOCK_POSITION === 'bottom' && {
133+ bottom : `calc(${ toolbarOffset + DOCK_MARGIN } px + env(safe-area-inset-bottom))` ,
134+ } ) ,
144135 } ;
145- if ( DOCK_POSITION === 'bottom' ) {
146- outerStyle . bottom = `calc(${ toolbarOffset + DOCK_MARGIN } px + env(safe-area-inset-bottom))` ;
147- }
148136
149137 const DOT_SIZE = 8 ;
150138
151139 return (
152140 < div
153141 ref = { outerRef }
154142 style = { outerStyle }
155- onTouchStart = { paginationEnabled ? handleTouchStart : null }
156- onTouchEnd = { paginationEnabled ? handleTouchEnd : null }
143+ onTouchStart = { paginationEnabled ? handleTouchStart : undefined }
144+ onTouchEnd = { paginationEnabled ? handleTouchEnd : undefined }
157145 >
158- < div
159- style = { {
160- display : 'flex' ,
161- flexDirection : 'column' ,
162- alignItems : 'center' ,
163- position : 'relative' ,
164- } }
165- >
146+ < div style = { { display : 'flex' , flexDirection : 'column' , alignItems : 'center' , position : 'relative' } } >
166147 < div
167148 ref = { iconsContainerRef }
168149 style = { getIconsContainerStyle ( isVerticalDock , DOCK_POSITION , ICON_SIZE , containerDimension ) }
@@ -172,68 +153,62 @@ export default function Dock() {
172153 >
173154 < div style = { getBackgroundStyle ( isVerticalDock , bgStart , bgSize , DOCK_POSITION ) } />
174155
175- { appsToRender . map ( ( app , index ) => (
176- < div
177- key = { app . id }
178- style = { {
179- ...getIconContainerStyle ( {
180- index,
181- paginationEnabled,
182- scales,
183- currentPage,
184- iconsPerPage,
185- ICON_SIZE ,
186- ICON_MARGIN ,
187- ADDITIONAL_MARGIN ,
188- shouldTransition,
189- INITIAL_TRANSITION ,
190- NO_TRANSITION ,
191- DOCK_POSITION ,
192- } ) ,
193- position : 'relative' ,
194- } }
195- onClick = { ( ) => openApp ( app ) }
196- onMouseEnter = { ( ) => handleIconMouseEnter ( app . id ) }
197- onMouseLeave = { handleIconMouseLeave }
198- >
199- { ! paginationEnabled && (
200- < div style = { getTooltipWrapperStyle ( DOCK_POSITION , APP_NAME_TOOLTIP_OFFSET ) } >
201- < div
202- style = { {
203- ...getTooltipBubbleStyle ( APP_NAME_BACKGROUND_PADDING , APP_NAME_FONT_SIZE ) ,
204- opacity : hoveredApp === app . id ? 1 : 0 ,
205- transition : hoveredApp === null ? 'opacity 0.3s ease' : 'none' ,
206- pointerEvents : 'none' ,
207- } }
208- >
209- { app . name }
210- < div style = { getTooltipArrowStyle ( DOCK_POSITION ) } />
156+ { appsToRender . map ( ( app , idx ) => {
157+ const isOpen = openedApps . includes ( app . id ) ;
158+ return (
159+ < div
160+ key = { app . id }
161+ style = { {
162+ ...getIconContainerStyle ( {
163+ index : idx ,
164+ paginationEnabled,
165+ scales,
166+ currentPage,
167+ iconsPerPage,
168+ ICON_SIZE ,
169+ ICON_MARGIN ,
170+ ADDITIONAL_MARGIN ,
171+ shouldTransition,
172+ INITIAL_TRANSITION ,
173+ NO_TRANSITION ,
174+ DOCK_POSITION ,
175+ } ) ,
176+ position : 'relative' ,
177+ } }
178+ onClick = { ( ) => openApp ( app . id ) }
179+ onMouseEnter = { ( ) => handleIconMouseEnter ( app . id ) }
180+ onMouseLeave = { handleIconMouseLeave }
181+ >
182+ { ! paginationEnabled && (
183+ < div style = { getTooltipWrapperStyle ( DOCK_POSITION , APP_NAME_TOOLTIP_OFFSET ) } >
184+ < div
185+ style = { {
186+ ...getTooltipBubbleStyle ( APP_NAME_BACKGROUND_PADDING , APP_NAME_FONT_SIZE ) ,
187+ opacity : hoveredApp === app . id ? 1 : 0 ,
188+ transition : hoveredApp === null ? 'opacity 0.3s ease' : 'none' ,
189+ pointerEvents : 'none' ,
190+ } }
191+ >
192+ { app . name }
193+ < div style = { getTooltipArrowStyle ( DOCK_POSITION ) } />
194+ </ div >
211195 </ div >
212- </ div >
213- ) }
214-
215- < img src = { app . icon } alt = { app . name } style = { iconImageStyle } />
216-
217- { ! app . available && (
218- < img
219- src = { disabledOverlay }
220- alt = { `${ app . name } disabled` }
221- style = { {
222- ...iconImageStyle ,
223- position : 'absolute' ,
224- top : 0 ,
225- left : 0 ,
226- opacity : 0.9 ,
227- pointerEvents : 'none' ,
228- } }
229- />
230- ) }
231-
232- { activeApp === app . id && (
233- < div style = { getOpenIndicatorStyle ( DOCK_POSITION ) } />
234- ) }
235- </ div >
236- ) ) }
196+ ) }
197+
198+ < img src = { app . icon } alt = { app . name } style = { iconImageStyle } />
199+
200+ { ! app . available && (
201+ < img
202+ src = { disabledOverlay }
203+ alt = { `${ app . name } disabled` }
204+ style = { { ...iconImageStyle , position : 'absolute' , top : 0 , left : 0 , opacity : 0.9 , pointerEvents : 'none' } }
205+ />
206+ ) }
207+
208+ { isOpen && < div style = { getOpenIndicatorStyle ( DOCK_POSITION ) } /> }
209+ </ div >
210+ ) ;
211+ } ) }
237212 </ div >
238213
239214 { paginationEnabled && totalPages > 1 && (
@@ -247,16 +222,16 @@ export default function Dock() {
247222 justifyContent : 'center' ,
248223 } }
249224 >
250- { Array . from ( { length : totalPages } ) . map ( ( _ , idx ) => (
225+ { Array . from ( { length : totalPages } ) . map ( ( _ , i ) => (
251226 < div
252- key = { idx }
253- onClick = { ( ) => setCurrentPage ( idx ) }
227+ key = { i }
228+ onClick = { ( ) => setCurrentPage ( i ) }
254229 style = { {
255230 width : `${ DOT_SIZE } px` ,
256231 height : `${ DOT_SIZE } px` ,
257232 borderRadius : '50%' ,
258233 margin : '0 4px' ,
259- background : idx === currentPage ? 'white' : 'black' ,
234+ background : i === currentPage ? 'white' : 'black' ,
260235 cursor : 'pointer' ,
261236 } }
262237 />
0 commit comments