Skip to content

Commit 094e0fe

Browse files
committed
fix: enhance viewcontroller error management with stateaware controllers
1 parent b72ef4b commit 094e0fe

10 files changed

Lines changed: 296 additions & 132 deletions

File tree

CONTRIBUTING.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ yarn run example detox:test:ios-release
143143
```
144144

145145
Android:
146+
147+
> [!NOTE]
148+
> Create emulator named "Android_Emulator" first if you don't have one already:
146149
```bash
147150
yarn run example detox:test:android-release
148151
```

example/.detoxrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ module.exports = {
7171
emulator: {
7272
type: 'android.emulator',
7373
device: {
74-
avdName: 'Pixel_9_Pro_API_35',
74+
avdName: 'Android_Emulator',
7575
},
7676
},
7777
},

example/src/controls/mapsControls.tsx

Lines changed: 90 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -129,93 +129,113 @@ const MapsControls = ({
129129
};
130130

131131
const getMyLocation = async () => {
132-
const result = await mapViewController.getMyLocation();
133-
log(`My location: ${JSON.stringify(result)}`);
132+
try {
133+
const result = await mapViewController.getMyLocation();
134+
log(`My location: ${JSON.stringify(result)}`);
135+
} catch (error) {
136+
log(`Error getting location: ${error}`);
137+
}
134138
};
135139

136140
const addMarker = async (imgPath?: string) => {
137-
const cameraPosition = await mapViewController.getCameraPosition();
138-
139-
const marker: Marker = await mapViewController.addMarker({
140-
position: cameraPosition.target,
141-
visible: true,
142-
title: 'Marker test',
143-
snippet: 'Marker test',
144-
alpha: 0.8,
145-
rotation: 0,
146-
flat: false,
147-
draggable: true,
148-
imgPath: imgPath,
149-
});
141+
try {
142+
const cameraPosition = await mapViewController.getCameraPosition();
143+
144+
const marker: Marker = await mapViewController.addMarker({
145+
position: cameraPosition.target,
146+
visible: true,
147+
title: 'Marker test',
148+
snippet: 'Marker test',
149+
alpha: 0.8,
150+
rotation: 0,
151+
flat: false,
152+
draggable: true,
153+
imgPath: imgPath,
154+
});
150155

151-
log(`Added marker: ${marker.id}`);
156+
log(`Added marker: ${marker.id}`);
157+
} catch (error) {
158+
log(`Error adding marker: ${error}`);
159+
}
152160
};
153161

154162
const addCustomMarker = async () => {
155163
addMarker('circle.png');
156164
};
157165

158166
const addCircle = async () => {
159-
const cameraPosition = await mapViewController.getCameraPosition();
160-
161-
const circle: Circle = await mapViewController.addCircle({
162-
center: cameraPosition.target,
163-
radius: 100,
164-
fillColor: '#FFFFFF',
165-
strokeColor: '#000000',
166-
strokeWidth: 5,
167-
visible: true,
168-
clickable: true,
169-
});
167+
try {
168+
const cameraPosition = await mapViewController.getCameraPosition();
169+
170+
const circle: Circle = await mapViewController.addCircle({
171+
center: cameraPosition.target,
172+
radius: 100,
173+
fillColor: '#FFFFFF',
174+
strokeColor: '#000000',
175+
strokeWidth: 5,
176+
visible: true,
177+
clickable: true,
178+
});
170179

171-
log(`Added circle: ${circle.id}`);
180+
log(`Added circle: ${circle.id}`);
181+
} catch (error) {
182+
log(`Error adding circle: ${error}`);
183+
}
172184
};
173185

174186
const addPolyline = async () => {
175-
const cameraPosition = await mapViewController.getCameraPosition();
176-
177-
const latLngs = [];
178-
179-
for (let idx = 0; idx < 100; idx++) {
180-
latLngs.push({
181-
lat: cameraPosition.target.lat + idx / 10000,
182-
lng: cameraPosition.target.lng + idx / 10000,
187+
try {
188+
const cameraPosition = await mapViewController.getCameraPosition();
189+
190+
const latLngs = [];
191+
192+
for (let idx = 0; idx < 100; idx++) {
193+
latLngs.push({
194+
lat: cameraPosition.target.lat + idx / 10000,
195+
lng: cameraPosition.target.lng + idx / 10000,
196+
});
197+
}
198+
199+
const polyline: Polyline = await mapViewController.addPolyline({
200+
points: latLngs,
201+
width: 10,
202+
color: '#f52525',
203+
visible: true,
204+
clickable: true,
183205
});
184-
}
185-
186-
const polyline: Polyline = await mapViewController.addPolyline({
187-
points: latLngs,
188-
width: 10,
189-
color: '#f52525',
190-
visible: true,
191-
clickable: true,
192-
});
193206

194-
log(`Added polyline: ${polyline.id}`);
207+
log(`Added polyline: ${polyline.id}`);
208+
} catch (error) {
209+
log(`Error adding polyline: ${error}`);
210+
}
195211
};
196212

197213
const addPolygon = async () => {
198-
const cameraPosition = await mapViewController.getCameraPosition();
199-
const cameraLat = cameraPosition.target.lat;
200-
const cameraLng = cameraPosition.target.lng;
201-
const delta = 0.05;
202-
const bermudaTriangle = [
203-
{ lat: cameraLat - delta, lng: cameraLng - delta },
204-
{ lat: cameraLat - delta, lng: cameraLng + delta },
205-
{ lat: cameraLat + delta, lng: cameraLng + delta },
206-
{ lat: cameraLat - delta, lng: cameraLng - delta },
207-
];
208-
209-
const polygon: Polygon = await mapViewController.addPolygon({
210-
strokeColor: '#FF00FF',
211-
fillColor: '#f52525',
212-
strokeWidth: 10,
213-
visible: true,
214-
points: bermudaTriangle,
215-
clickable: true,
216-
});
214+
try {
215+
const cameraPosition = await mapViewController.getCameraPosition();
216+
const cameraLat = cameraPosition.target.lat;
217+
const cameraLng = cameraPosition.target.lng;
218+
const delta = 0.05;
219+
const bermudaTriangle = [
220+
{ lat: cameraLat - delta, lng: cameraLng - delta },
221+
{ lat: cameraLat - delta, lng: cameraLng + delta },
222+
{ lat: cameraLat + delta, lng: cameraLng + delta },
223+
{ lat: cameraLat - delta, lng: cameraLng - delta },
224+
];
225+
226+
const polygon: Polygon = await mapViewController.addPolygon({
227+
strokeColor: '#FF00FF',
228+
fillColor: '#f52525',
229+
strokeWidth: 10,
230+
visible: true,
231+
points: bermudaTriangle,
232+
clickable: true,
233+
});
217234

218-
log(`Added polygon: ${polygon.id}`);
235+
log(`Added polygon: ${polygon.id}`);
236+
} catch (error) {
237+
log(`Error adding polygon: ${error}`);
238+
}
219239
};
220240

221241
const clearMapView = () => {
@@ -303,7 +323,7 @@ const MapsControls = ({
303323
{/* Map Appearance */}
304324
<Accordion title="Map Appearance">
305325
<View style={ControlStyles.rowContainer}>
306-
<Text>Map type</Text>
326+
<Text style={ControlStyles.rowLabel}>Map type</Text>
307327
<SelectDropdown
308328
data={mapTypeOptions}
309329
onSelect={(_selectedItem, index) => {
@@ -334,7 +354,7 @@ const MapsControls = ({
334354
/>
335355
</View>
336356
<View style={ControlStyles.rowContainer}>
337-
<Text>Map color scheme</Text>
357+
<Text style={ControlStyles.rowLabel}>Map color scheme</Text>
338358
<SelectDropdown
339359
data={colorSchemeOptions}
340360
defaultValueByIndex={colorSchemeIndex}
@@ -366,7 +386,7 @@ const MapsControls = ({
366386
/>
367387
</View>
368388
<View style={ControlStyles.rowContainer}>
369-
<Text>Custom map paddings</Text>
389+
<Text style={ControlStyles.rowLabel}>Custom map paddings</Text>
370390
<ExampleAppButton
371391
title={customPaddingEnabled ? 'Disable' : 'Enable'}
372392
onPress={toggleCustomPadding}
@@ -377,7 +397,7 @@ const MapsControls = ({
377397
{/* Location & UI */}
378398
<Accordion title="Location & UI Settings">
379399
<View style={ControlStyles.rowContainer}>
380-
<Text>Location marker</Text>
400+
<Text style={ControlStyles.rowLabel}>Location marker</Text>
381401
<ExampleAppButton
382402
title={enableLocationMarker ? 'Disable' : 'Enable'}
383403
onPress={() => {

example/src/controls/navigationControls.tsx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,9 @@ const NavigationControls = ({
428428
/>
429429
{Platform.OS === 'ios' && (
430430
<View style={ControlStyles.rowContainer}>
431-
<Text>Background location updates</Text>
431+
<Text style={ControlStyles.rowLabel}>
432+
Background location updates
433+
</Text>
432434
<ExampleAppButton
433435
title={backgroundLocationUpdatesEnabled ? 'Disable' : 'Enable'}
434436
onPress={() => {
@@ -444,7 +446,7 @@ const NavigationControls = ({
444446
{/* UI Display Options */}
445447
<Accordion title="UI Display Options">
446448
<View style={ControlStyles.rowContainer}>
447-
<Text>Navigation UI</Text>
449+
<Text style={ControlStyles.rowLabel}>Navigation UI</Text>
448450
<ExampleAppButton
449451
title={navigationUiEnabled ? 'Disable' : 'Enable'}
450452
onPress={() => {
@@ -453,7 +455,7 @@ const NavigationControls = ({
453455
/>
454456
</View>
455457
<View style={ControlStyles.rowContainer}>
456-
<Text>Header enabled</Text>
458+
<Text style={ControlStyles.rowLabel}>Header enabled</Text>
457459
<ExampleAppButton
458460
title={headerEnabled ? 'Disable' : 'Enable'}
459461
onPress={() => {
@@ -462,7 +464,7 @@ const NavigationControls = ({
462464
/>
463465
</View>
464466
<View style={ControlStyles.rowContainer}>
465-
<Text>Footer enabled</Text>
467+
<Text style={ControlStyles.rowLabel}>Footer enabled</Text>
466468
<ExampleAppButton
467469
title={footerEnabled ? 'Disable' : 'Enable'}
468470
onPress={() => {
@@ -471,7 +473,7 @@ const NavigationControls = ({
471473
/>
472474
</View>
473475
<View style={ControlStyles.rowContainer}>
474-
<Text>Trip progress bar</Text>
476+
<Text style={ControlStyles.rowLabel}>Trip progress bar</Text>
475477
<ExampleAppButton
476478
title={tripProgressBarEnabled ? 'Disable' : 'Enable'}
477479
onPress={() => {
@@ -483,7 +485,7 @@ const NavigationControls = ({
483485
/>
484486
</View>
485487
<View style={ControlStyles.rowContainer}>
486-
<Text>Recenter button</Text>
488+
<Text style={ControlStyles.rowLabel}>Recenter button</Text>
487489
<ExampleAppButton
488490
title={recenterButtonEnabled ? 'Disable' : 'Enable'}
489491
onPress={() => {
@@ -492,7 +494,7 @@ const NavigationControls = ({
492494
/>
493495
</View>
494496
<View style={ControlStyles.rowContainer}>
495-
<Text>Report incident button</Text>
497+
<Text style={ControlStyles.rowLabel}>Report incident button</Text>
496498
<ExampleAppButton
497499
title={reportIncidentButtonEnabled ? 'Disable' : 'Enable'}
498500
onPress={() => {
@@ -504,7 +506,7 @@ const NavigationControls = ({
504506
/>
505507
</View>
506508
<View style={ControlStyles.rowContainer}>
507-
<Text>Traffic incidents card</Text>
509+
<Text style={ControlStyles.rowLabel}>Traffic incidents card</Text>
508510
<ExampleAppButton
509511
title={trafficIncidentCardsEnabled ? 'Disable' : 'Enable'}
510512
onPress={() => {
@@ -517,7 +519,7 @@ const NavigationControls = ({
517519
{/* Speed & Safety */}
518520
<Accordion title="Speed & Safety">
519521
<View style={ControlStyles.rowContainer}>
520-
<Text>Speed limit icon</Text>
522+
<Text style={ControlStyles.rowLabel}>Speed limit icon</Text>
521523
<ExampleAppButton
522524
title={speedLimitIconEnabled ? 'Disable' : 'Enable'}
523525
onPress={() => {
@@ -526,7 +528,7 @@ const NavigationControls = ({
526528
/>
527529
</View>
528530
<View style={ControlStyles.rowContainer}>
529-
<Text>Speedometer</Text>
531+
<Text style={ControlStyles.rowLabel}>Speedometer</Text>
530532
<ExampleAppButton
531533
title={speedometerEnabled ? 'Disable' : 'Enable'}
532534
onPress={() => {
@@ -543,7 +545,7 @@ const NavigationControls = ({
543545
{/* Appearance */}
544546
<Accordion title="Appearance">
545547
<View style={ControlStyles.rowContainer}>
546-
<Text>Night mode</Text>
548+
<Text style={ControlStyles.rowLabel}>Night mode</Text>
547549
<SelectDropdown
548550
data={nightModeOptions}
549551
defaultValueByIndex={nightModeIndex}
@@ -575,7 +577,7 @@ const NavigationControls = ({
575577
/>
576578
</View>
577579
<View style={ControlStyles.rowContainer}>
578-
<Text>Camera perspective</Text>
580+
<Text style={ControlStyles.rowLabel}>Camera perspective</Text>
579581
<SelectDropdown
580582
data={perspectiveOptions}
581583
onSelect={(_selectedItem, index) => {
@@ -618,7 +620,7 @@ const NavigationControls = ({
618620
{/* Audio & Logging */}
619621
<Accordion title="Audio & Logging">
620622
<View style={ControlStyles.rowContainer}>
621-
<Text>Audio guidance type</Text>
623+
<Text style={ControlStyles.rowLabel}>Audio guidance type</Text>
622624
<SelectDropdown
623625
data={audioGuidanceOptions}
624626
onSelect={(_selectedItem, index) => {
@@ -649,7 +651,7 @@ const NavigationControls = ({
649651
/>
650652
</View>
651653
<View style={ControlStyles.rowContainer}>
652-
<Text>Turn-by-turn logging</Text>
654+
<Text style={ControlStyles.rowLabel}>Turn-by-turn logging</Text>
653655
<ExampleAppButton
654656
title={turnByTurnLoggingEnabled ? 'Disable' : 'Enable'}
655657
onPress={() => {

example/src/styles/components.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ export const ControlStyles = StyleSheet.create({
235235
alignItems: 'center',
236236
},
237237

238+
rowLabel: {
239+
color: Colors.text,
240+
},
241+
238242
// Form inputs
239243
input: {
240244
backgroundColor: Colors.surface,

src/maps/mapView/mapView.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,15 @@ export const MapView = (props: MapViewProps): React.JSX.Element => {
4646
}
4747
};
4848

49+
// Create controller when viewId changes
4950
useEffect(() => {
5051
if (!mapViewRef.current) {
5152
return;
5253
}
5354
const _viewId = findNodeHandle(mapViewRef.current) || 0;
5455
if (viewId !== _viewId) {
5556
setViewId(_viewId);
56-
onMapViewControllerCreated(getMapViewController(_viewId));
57+
onMapViewControllerCreated(getMapViewController(mapViewRef));
5758
}
5859
}, [onMapViewControllerCreated, viewId]);
5960

0 commit comments

Comments
 (0)