Skip to content

Commit d857172

Browse files
Merge pull request #44 from HaudinFlorence/adapt_ManualControl_for_short_and_longer_clicks
Adapt Manual Control component logics for short and longer clicks
2 parents 548be2b + 118b6a8 commit d857172

1 file changed

Lines changed: 178 additions & 69 deletions

File tree

src/movehub-extension/components/ManualControl.tsx

Lines changed: 178 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,74 @@ const arrowDownSVGUrl = `data:image/svg+xml;base64,${btoa(arrowDownSVG)}`;
1515
const turnLeftSVGUrl = `data:image/svg+xml;base64,${btoa(turnLeftSVG)}`;
1616
const turnRightSVGUrl = `data:image/svg+xml;base64,${btoa(turnRightSVG)}`;
1717
import { UseSignal } from '@jupyterlab/apputils';
18+
import { Button } from '@jupyterlab/ui-components';
19+
import { Poll } from '@lumino/polling';
20+
const LONG_PRESS_THRESHOLD = 1000;
1821

1922
export interface IMoveHubControlProps {
2023
device: MoveHub;
2124
}
2225

2326
export function ManualControl({ device, themeManager }: IMoveHubPanelWithThemeProps) {
27+
let pressStartTime: number = 0;
28+
let pressDuration: number = 0;
29+
let poll: Poll | null = null;
30+
31+
const handleMouseDown = () => {
32+
pressStartTime = Date.now();
33+
34+
poll = new Poll({
35+
auto: true,
36+
name: 'click-duration-polling',
37+
factory: async () => {
38+
pressDuration = Date.now() - pressStartTime;
39+
},
40+
frequency: {
41+
interval: 100,
42+
backoff: true,
43+
},
44+
standby: 'when-hidden',
45+
});
46+
47+
poll.start();
48+
};
49+
50+
const handleMouseUp = async (action: string, direction: number) => {
51+
if (poll) {
52+
poll.stop();
53+
}
54+
if (action === "inactive") {
55+
console.error('Inactive button, no control available.');
56+
}
57+
if (action === "stop") {
58+
device.stop();
59+
}
60+
61+
if (pressDuration < LONG_PRESS_THRESHOLD) {
62+
if (action === "drive") {
63+
await device.hub.drive(20 * direction);
64+
}
65+
else if (action === "turn") {
66+
await device.hub.turn(90 * direction);
67+
}
68+
69+
} else {
70+
if (action === "drive") {
71+
await device.hub.driveToDirection(direction);
72+
}
73+
74+
else if (action === "turn") {
75+
await device.hub.turn(3600*direction);
76+
}
77+
};
78+
}
79+
80+
const handleMouseLeave = () => {
81+
if (poll) {
82+
poll.stop();
83+
}
84+
};
85+
2486
const theme = themeManager.theme;
2587
if (theme) {
2688
const isThemeLight = themeManager.isLight(theme!);
@@ -30,71 +92,91 @@ export function ManualControl({ device, themeManager }: IMoveHubPanelWithThemePr
3092
id: 1,
3193
src: currentEmptySVGUrl,
3294
alt: 'Image 1',
33-
handleClick: () => {
34-
console.error('Inactive button, no control available.');
35-
}
95+
action: "inactive",
96+
direction: 0,
97+
handleMouseDown: handleMouseDown,
98+
handleMouseUp: handleMouseUp,
99+
handleMouseLeave: handleMouseLeave
36100
},
37101
{
38102
id: 2,
39103
src: arrowUpSVGUrl,
40104
alt: 'Image 2',
41-
handleClick: async () => {
42-
await device.hub.driveToDirection(1);
43-
}
105+
action: 'drive',
106+
direction: 1,
107+
handleMouseDown: handleMouseDown,
108+
handleMouseUp: handleMouseUp,
109+
handleMouseLeave: handleMouseLeave
44110
},
45111
{
46112
id: 3,
47113
src: currentEmptySVGUrl,
48114
alt: 'Image 3',
49-
handleClick: () => {
50-
console.error('Inactive button, no control available.');
51-
}
115+
action: "inactive",
116+
direction: 0,
117+
handleMouseDown: handleMouseDown,
118+
handleMouseUp: handleMouseUp,
119+
handleMouseLeave: handleMouseLeave
52120
},
53121
{
54122
id: 4,
55123
src: turnLeftSVGUrl,
124+
action: "turn",
125+
direction: -1,
56126
alt: 'Image 4',
57-
handleClick: async () => {
58-
await device.hub.turn(-90);
59-
}
127+
handleMouseDown: handleMouseDown,
128+
handleMouseUp: handleMouseUp,
129+
handleMouseLeave: handleMouseLeave
60130
},
61131
{
62132
id: 5,
63133
src: stopSVGUrl,
64134
alt: 'Image 5',
65-
handleClick: async () => {
66-
device.stop();
67-
}
135+
action: "stop",
136+
direction: 0,
137+
handleMouseDown: handleMouseDown,
138+
handleMouseUp: handleMouseUp,
139+
handleMouseLeave: handleMouseLeave
68140
},
69141
{
70142
id: 6,
71143
src: turnRightSVGUrl,
72144
alt: 'Image 6',
73-
handleClick: async () => {
74-
device.hub.turn(90);
75-
}
145+
action: "turn",
146+
direction: 1,
147+
handleMouseDown: handleMouseDown,
148+
handleMouseUp: handleMouseUp,
149+
handleMouseLeave: handleMouseLeave
76150
},
77151
{
78152
id: 7,
79153
src: currentEmptySVGUrl,
80154
alt: 'Image 7',
81-
handleClick: () => {
82-
console.error('Inactive button, no control available.');
83-
}
155+
action: "inactive",
156+
direction: 0,
157+
handleMouseDown: handleMouseDown,
158+
handleMouseUp: handleMouseUp,
159+
handleMouseLeave: handleMouseLeave
84160
},
85161
{
86162
id: 8,
87163
src: arrowDownSVGUrl,
88164
alt: 'Image 8',
89-
handleClick: async () => await device.hub.driveToDirection(0)
165+
action: "drive",
166+
direction: -1,
167+
handleMouseDown: handleMouseDown,
168+
handleMouseUp: handleMouseUp,
169+
handleMouseLeave: handleMouseLeave
90170
},
91171
{
92172
id: 9,
93173
src: currentEmptySVGUrl,
94174
alt: 'Image 9',
95-
handleClick: () => {
96-
console.error('Inactive button, no control available.');
97-
}
175+
action: "inactive",
176+
direction: 0,
177+
handleMouseDown: handleMouseDown,
178+
handleMouseUp: handleMouseUp,
179+
handleMouseLeave: handleMouseLeave
98180
}
99181
];
100182

@@ -103,13 +185,15 @@ export function ManualControl({ device, themeManager }: IMoveHubPanelWithThemePr
103185
<div className="manual-control-grid">
104186
{images.map((image, index) => (
105187
<div className="manual-control-grid-item">
106-
<button
188+
<Button
107189
key={index}
108-
onClick={image.handleClick}
190+
onMouseDown={image.handleMouseDown}
191+
onMouseUp={(e) => { handleMouseUp(image.action, image.direction) }}
192+
onMouseLeave={image.handleMouseLeave}
109193
className="image-button"
110194
>
111195
<img src={image.src} alt={image.alt} />
112-
</button>
196+
</Button>
113197
</div>
114198
))}
115199
</div>
@@ -124,90 +208,115 @@ export function ManualControl({ device, themeManager }: IMoveHubPanelWithThemePr
124208
id: 1,
125209
src: emptyLightSVGUrl,
126210
alt: 'Image 1',
127-
handleClick: () => {
128-
console.error('Inactive button, no control available.');
129-
}
211+
action: "inactive",
212+
direction: 0,
213+
handleMouseDown: handleMouseDown,
214+
handleMouseUp: handleMouseUp,
215+
handleMouseLeave: handleMouseLeave
130216
},
131217
{
132218
id: 2,
133219
src: arrowUpSVGUrl,
134220
alt: 'Image 2',
135-
handleClick: async () => {
136-
await device.hub.driveToDirection(1);
137-
}
221+
action: 'drive',
222+
direction: 1,
223+
handleMouseDown: handleMouseDown,
224+
handleMouseUp: handleMouseUp,
225+
handleMouseLeave: handleMouseLeave
138226
},
139227
{
140228
id: 3,
141229
src: emptyLightSVGUrl,
142230
alt: 'Image 3',
143-
handleClick: () => {
144-
console.error('Inactive button, no control available.');
145-
}
231+
action: "inactive",
232+
direction: 0,
233+
handleMouseDown: handleMouseDown,
234+
handleMouseUp: handleMouseUp,
235+
handleMouseLeave: handleMouseLeave
146236
},
147237
{
148238
id: 4,
149239
src: turnLeftSVGUrl,
240+
action: "turn",
241+
direction: -1,
150242
alt: 'Image 4',
151-
handleClick: async () => {
152-
await device.hub.turn(-90);
153-
}
243+
handleMouseDown: handleMouseDown,
244+
handleMouseUp: handleMouseUp,
245+
handleMouseLeave: handleMouseLeave
154246
},
155247
{
156248
id: 5,
157249
src: stopSVGUrl,
158250
alt: 'Image 5',
159-
handleClick: async () => {
160-
device.stop();
161-
}
251+
action: "stop",
252+
direction: 0,
253+
handleMouseDown: handleMouseDown,
254+
handleMouseUp: handleMouseUp,
255+
handleMouseLeave: handleMouseLeave
162256
},
163257
{
164258
id: 6,
165259
src: turnRightSVGUrl,
166260
alt: 'Image 6',
167-
handleClick: async () => {
168-
device.hub.turn(90);
169-
}
261+
action: "turn",
262+
direction: 1,
263+
handleMouseDown: handleMouseDown,
264+
handleMouseUp: handleMouseUp,
265+
handleMouseLeave: handleMouseLeave
170266
},
171267
{
172268
id: 7,
173269
src: emptyLightSVGUrl,
174270
alt: 'Image 7',
175-
handleClick: () => {
176-
console.error('Inactive button, no control available.');
177-
}
271+
action: "inactive",
272+
direction: 0,
273+
handleMouseDown: handleMouseDown,
274+
handleMouseUp: handleMouseUp,
275+
handleMouseLeave: handleMouseLeave
178276
},
179277
{
180278
id: 8,
181279
src: arrowDownSVGUrl,
182280
alt: 'Image 8',
183-
handleClick: async () => await device.hub.driveToDirection(0)
281+
action: "drive",
282+
direction: -1,
283+
handleMouseDown: handleMouseDown,
284+
handleMouseUp: handleMouseUp,
285+
handleMouseLeave: handleMouseLeave
184286
},
185287
{
186288
id: 9,
187289
src: emptyLightSVGUrl,
188290
alt: 'Image 9',
189-
handleClick: () => {
190-
console.error('Inactive button, no control available.');
191-
}
291+
action: "inactive",
292+
direction: 0,
293+
handleMouseDown: handleMouseDown,
294+
handleMouseUp: handleMouseUp,
295+
handleMouseLeave: handleMouseLeave
192296
}
193297
];
194298

195-
return (
196-
<div className="manual-control-grid">
197-
{images.map((image, index) => (
198-
<div className="manual-control-grid-item">
199-
<button
200-
key={index}
201-
onClick={image.handleClick}
202-
className="image-button"
203-
>
204-
<img src={image.src} alt={image.alt} />
205-
</button>
206-
</div>
207-
))}
208-
</div>
209-
)
299+
return (<UseSignal signal={themeManager.themeChanged}>
300+
{(): JSX.Element => (
301+
<div className="manual-control-grid">
302+
{images.map((image, index) => (
303+
<div className="manual-control-grid-item">
304+
<Button
305+
key={index}
306+
onMouseDown={image.handleMouseDown}
307+
onMouseUp={(e) => { handleMouseUp(image.action, image.direction) }}
308+
onMouseLeave={image.handleMouseLeave}
309+
310+
className="image-button"
311+
>
312+
<img src={image.src} alt={image.alt} />
313+
</Button>
314+
</div>
315+
))}
316+
</div>
317+
)}
318+
</UseSignal>
319+
);
210320
}
211321
}
212322

213-

0 commit comments

Comments
 (0)