Skip to content

Commit 6f031a3

Browse files
committed
#44 bug fixed. DesktopAssembler rearranged. Dock logic rearranged.
1 parent 3d1b529 commit 6f031a3

7 files changed

Lines changed: 307 additions & 460 deletions

File tree

src/webOS/components/Dock/Dock.jsx

Lines changed: 95 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -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

2323
export 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

Comments
 (0)