Skip to content

Commit feafd79

Browse files
fix: address CodeRabbit follow-up comments
1 parent 8b65568 commit feafd79

4 files changed

Lines changed: 87 additions & 20 deletions

File tree

example/App.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ type ScenarioDockProps = {
231231
expanded: boolean;
232232
mapTypeLabel: MapType;
233233
providerLabel: string;
234+
canCycleProvider: boolean;
234235
onToggleExpanded: () => void;
235236
onSelect: (index: number) => void;
236237
onAnimateCamera: () => void;
@@ -245,6 +246,7 @@ const ScenarioDock = memo(function ScenarioDock({
245246
expanded,
246247
mapTypeLabel,
247248
providerLabel,
249+
canCycleProvider,
248250
onToggleExpanded,
249251
onSelect,
250252
onAnimateCamera,
@@ -313,10 +315,12 @@ const ScenarioDock = memo(function ScenarioDock({
313315
{MAP_TYPE_LABELS[mapTypeLabel]}
314316
</Text>
315317
</ScalePressable>
316-
<ScalePressable onPress={onCycleProvider} style={styles.actionButton}>
317-
<Text style={styles.actionButtonIcon}></Text>
318-
<Text style={styles.actionButtonText}>{providerLabel}</Text>
319-
</ScalePressable>
318+
{canCycleProvider ? (
319+
<ScalePressable onPress={onCycleProvider} style={styles.actionButton}>
320+
<Text style={styles.actionButtonIcon}></Text>
321+
<Text style={styles.actionButtonText}>{providerLabel}</Text>
322+
</ScalePressable>
323+
) : null}
320324
</View>
321325
</Animated.View>
322326
) : null}
@@ -648,6 +652,7 @@ export default function App() {
648652
expanded={dockExpanded}
649653
mapTypeLabel={MAP_TYPES[mapTypeIndex]}
650654
providerLabel={PROVIDER_LABELS[provider]}
655+
canCycleProvider={SUPPORTED_MAP_PROVIDERS.length > 1}
651656
onToggleExpanded={toggleDockExpanded}
652657
onSelect={selectScenario}
653658
onAnimateCamera={handleAnimateCamera}

package/ios/AppleMapProviderAdapter.swift

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import UIKit
55
final class AppleMapProviderAdapter: MapProviderAdapter {
66
private let mapViewDelegate = HybridMapViewDelegate()
77
private var isProgrammaticUpdate = false
8+
private var pendingProgrammaticUpdateIDs: [Int] = []
9+
private var nextProgrammaticUpdateID = 0
810
private var isMapReady = false
911
private var hasDeliveredMapReady = false
1012
private var liveClusterTimer: Timer?
@@ -210,34 +212,47 @@ final class AppleMapProviderAdapter: MapProviderAdapter {
210212
}
211213

212214
let edgePadding = padding?.toUIEdgeInsets() ?? .zero
213-
isProgrammaticUpdate = true
215+
let shouldAnimate = animated ?? true
216+
let updateID = beginProgrammaticUpdate()
214217
view.setVisibleMapRect(
215218
mapRect,
216219
edgePadding: edgePadding,
217-
animated: animated ?? true
220+
animated: shouldAnimate
221+
)
222+
scheduleProgrammaticUpdateFallback(
223+
for: updateID,
224+
delay: shouldAnimate ? 1.0 : 0
218225
)
219-
isProgrammaticUpdate = false
220226
}
221227

222228
func applyRegion(_ region: Region, animated: Bool = false) {
223-
isProgrammaticUpdate = true
229+
let updateID = beginProgrammaticUpdate()
224230
view.setRegion(region.toMKCoordinateRegion(), animated: animated)
225-
isProgrammaticUpdate = false
231+
scheduleProgrammaticUpdateFallback(
232+
for: updateID,
233+
delay: animated ? 1.0 : 0
234+
)
226235
}
227236

228237
func updateMapCamera(_ camera: Camera, animated: Bool, duration: Double = 0) {
229-
isProgrammaticUpdate = true
238+
let updateID = beginProgrammaticUpdate()
230239
let mapCamera = camera.toMKMapCamera()
231240

232241
if animated {
233-
UIView.animate(withDuration: duration) {
234-
self.view.camera = mapCamera
235-
}
242+
UIView.animate(
243+
withDuration: duration,
244+
animations: {
245+
self.view.camera = mapCamera
246+
},
247+
completion: { [weak self] _ in
248+
self?.endProgrammaticUpdate(updateID)
249+
}
250+
)
251+
scheduleProgrammaticUpdateFallback(for: updateID, delay: duration + 0.1)
236252
} else {
237253
view.camera = mapCamera
254+
scheduleProgrammaticUpdateFallback(for: updateID, delay: 0)
238255
}
239-
240-
isProgrammaticUpdate = false
241256
}
242257

243258
// Derived from MKCoordinateRegion (center + span). May differ from Android
@@ -254,6 +269,45 @@ final class AppleMapProviderAdapter: MapProviderAdapter {
254269
view.setRegion(view.regionThatFits(region), animated: true)
255270
}
256271

272+
private func beginProgrammaticUpdate() -> Int {
273+
nextProgrammaticUpdateID += 1
274+
let updateID = nextProgrammaticUpdateID
275+
pendingProgrammaticUpdateIDs.append(updateID)
276+
isProgrammaticUpdate = true
277+
return updateID
278+
}
279+
280+
private func endProgrammaticUpdate(_ updateID: Int? = nil) {
281+
if let updateID {
282+
guard let index = pendingProgrammaticUpdateIDs.firstIndex(of: updateID) else {
283+
return
284+
}
285+
pendingProgrammaticUpdateIDs.remove(at: index)
286+
} else if !pendingProgrammaticUpdateIDs.isEmpty {
287+
pendingProgrammaticUpdateIDs.removeFirst()
288+
}
289+
290+
isProgrammaticUpdate = !pendingProgrammaticUpdateIDs.isEmpty
291+
}
292+
293+
func endProgrammaticRegionChangeIfNeeded() {
294+
guard !pendingProgrammaticUpdateIDs.isEmpty else {
295+
return
296+
}
297+
298+
endProgrammaticUpdate()
299+
}
300+
301+
private func scheduleProgrammaticUpdateFallback(for updateID: Int, delay: TimeInterval) {
302+
DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
303+
guard let self else {
304+
return
305+
}
306+
307+
self.endProgrammaticUpdate(updateID)
308+
}
309+
}
310+
257311
func startLiveClustering() {
258312
guard liveClusterTimer == nil else {
259313
return
@@ -340,6 +394,7 @@ final class AppleMapProviderAdapter: MapProviderAdapter {
340394
liveClusterTimer?.invalidate()
341395
liveClusterTimer = nil
342396
isProgrammaticUpdate = false
397+
pendingProgrammaticUpdateIDs.removeAll()
343398
isMapReady = false
344399
hasDeliveredMapReady = false
345400
onRegionChange = nil

package/ios/HybridMapViewDelegate.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ final class HybridMapViewDelegate: NSObject, MKMapViewDelegate, UIGestureRecogni
7474
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
7575
parent?.stopLiveClustering()
7676
parent?.notifyRegionChange(complete: true)
77+
parent?.endProgrammaticRegionChangeIfNeeded()
7778
}
7879

7980
func mapViewDidFinishLoadingMap(_ mapView: MKMapView) {

package/scripts/patch-nitrogen-generated.mjs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@ const packageDir = join(scriptDir, '..');
77

88
function replaceOnce(filePath, from, to) {
99
const source = readFileSync(filePath, 'utf8');
10-
if (!source.includes(from)) {
11-
if (source.includes(to)) {
12-
return;
13-
}
14-
throw new Error(`Expected generated code was not found in ${filePath}`);
10+
const fromCount = source.split(from).length - 1;
11+
const toCount = source.split(to).length - 1;
12+
13+
if (fromCount === 0 && toCount === 1) {
14+
return;
15+
}
16+
17+
if (fromCount !== 1) {
18+
throw new Error(
19+
`Expected exactly one patch target in ${filePath}, found ${fromCount}`,
20+
);
1521
}
1622

1723
writeFileSync(filePath, source.replace(from, to));

0 commit comments

Comments
 (0)