|
1 | 1 | package com.mapbox.navigation.base.internal.route |
2 | 2 |
|
3 | | -import com.google.gson.JsonArray |
4 | | -import com.google.gson.JsonElement |
5 | | -import com.mapbox.navigation.base.internal.utils.Constants.NotificationRefreshType.DYNAMIC |
| 3 | +import com.mapbox.api.directions.v5.DirectionsCriteria.NOTIFICATION_REFRESH_TYPE_DYNAMIC |
| 4 | +import com.mapbox.api.directions.v5.models.Notification |
6 | 5 |
|
7 | 6 | internal class NotificationsRefresher { |
8 | 7 |
|
9 | 8 | fun getRefreshedNotifications( |
10 | | - oldNotifications: JsonArray?, |
11 | | - newNotifications: JsonArray?, |
| 9 | + oldNotifications: List<Notification>?, |
| 10 | + newNotifications: List<Notification>?, |
12 | 11 | startingLegGeometryIndex: Int, |
13 | 12 | lastRefreshLegGeometryIndex: Int, |
14 | | - ): JsonArray? { |
15 | | - return when { |
| 13 | + ): List<Notification>? { |
| 14 | + val result = when { |
16 | 15 | oldNotifications == null && newNotifications == null -> null |
17 | 16 | oldNotifications == null -> adjustNotificationIndices( |
18 | | - newNotifications, |
| 17 | + newNotifications.orEmpty(), |
19 | 18 | startingLegGeometryIndex, |
20 | 19 | ) |
| 20 | + |
21 | 21 | newNotifications == null -> filterNotificationsByGeometryRange( |
22 | 22 | oldNotifications, |
23 | 23 | startingLegGeometryIndex, |
24 | 24 | lastRefreshLegGeometryIndex, |
25 | 25 | ) |
| 26 | + |
26 | 27 | else -> mergeNotifications( |
27 | 28 | oldNotifications, |
28 | 29 | newNotifications, |
29 | 30 | startingLegGeometryIndex, |
30 | 31 | lastRefreshLegGeometryIndex, |
31 | 32 | ) |
32 | 33 | } |
| 34 | + |
| 35 | + return result?.takeIf { it.isNotEmpty() } |
33 | 36 | } |
34 | 37 |
|
35 | 38 | private fun mergeNotifications( |
36 | | - oldNotifications: JsonArray, |
37 | | - newNotifications: JsonArray, |
| 39 | + oldNotifications: List<Notification>, |
| 40 | + newNotifications: List<Notification>, |
38 | 41 | startingLegGeometryIndex: Int, |
39 | 42 | lastRefreshLegGeometryIndex: Int, |
40 | | - ): JsonArray { |
| 43 | + ): List<Notification> { |
41 | 44 | // Filter old notifications to keep static and dynamic notifications outside refresh range |
42 | | - val result = filterNotificationsByGeometryRange( |
| 45 | + val oldFiltered = filterNotificationsByGeometryRange( |
43 | 46 | oldNotifications, |
44 | 47 | startingLegGeometryIndex, |
45 | 48 | lastRefreshLegGeometryIndex, |
46 | 49 | ) |
47 | 50 |
|
48 | 51 | // Add new dynamic notifications with adjusted indices |
49 | | - result.addAll( |
50 | | - adjustNotificationIndices( |
51 | | - newNotifications, |
52 | | - startingLegGeometryIndex, |
53 | | - ), |
| 52 | + val newAdjusted = adjustNotificationIndices( |
| 53 | + newNotifications, |
| 54 | + startingLegGeometryIndex, |
54 | 55 | ) |
55 | 56 |
|
56 | | - return result |
| 57 | + return oldFiltered + newAdjusted |
57 | 58 | } |
58 | 59 |
|
59 | 60 | private fun filterNotificationsByGeometryRange( |
60 | | - notifications: JsonArray, |
| 61 | + notifications: List<Notification>, |
61 | 62 | startingLegGeometryIndex: Int, |
62 | 63 | lastRefreshLegGeometryIndex: Int, |
63 | | - ): JsonArray { |
64 | | - val result = JsonArray() |
65 | | - |
66 | | - notifications.forEach { notification -> |
67 | | - if (notification.isDynamicNotification()) { |
| 64 | + ): List<Notification> = |
| 65 | + notifications.mapNotNull { notification -> |
| 66 | + if (notification.isDynamic) { |
68 | 67 | // Dynamic notifications: only keep those outside the refresh range |
69 | | - val geometryIndex = notification.getGeometryIndex() |
| 68 | + val geometryIndex = notification.geometryIndex() |
70 | 69 | if (geometryIndex != null) { |
71 | 70 | val isOutsideRange = geometryIndex < startingLegGeometryIndex || |
72 | 71 | geometryIndex > lastRefreshLegGeometryIndex |
73 | 72 | if (isOutsideRange) { |
74 | | - result.add(notification) |
| 73 | + return@mapNotNull notification |
75 | 74 | } |
76 | 75 | } |
77 | 76 | // Dynamic notifications without geometry_index are filtered out |
| 77 | + null |
78 | 78 | } else { |
79 | 79 | // Static notifications: always keep them |
80 | | - result.add(notification) |
| 80 | + notification |
81 | 81 | } |
82 | 82 | } |
83 | 83 |
|
84 | | - return result |
85 | | - } |
86 | | - |
87 | 84 | /** |
88 | 85 | * Adjusts geometry indices for new notifications using the provided starting leg geometry index. |
89 | 86 | */ |
90 | 87 | private fun adjustNotificationIndices( |
91 | | - notifications: JsonArray?, |
| 88 | + notifications: List<Notification>, |
92 | 89 | startingLegGeometryIndex: Int, |
93 | | - ): JsonArray? { |
94 | | - if (notifications == null || notifications.isEmpty) { |
95 | | - return notifications |
96 | | - } |
97 | | - |
98 | | - val result = JsonArray() |
99 | | - notifications.forEach { notification -> |
100 | | - val adjustedNotification = adjustNotificationIndex( |
| 90 | + ): List<Notification> = |
| 91 | + notifications.map { notification -> |
| 92 | + adjustNotificationIndex( |
101 | 93 | notification, |
102 | 94 | startingLegGeometryIndex, |
103 | 95 | ) |
104 | | - result.add(adjustedNotification) |
105 | 96 | } |
106 | | - return result |
107 | | - } |
108 | 97 |
|
109 | 98 | private fun adjustNotificationIndex( |
110 | | - notification: JsonElement, |
| 99 | + notification: Notification, |
111 | 100 | startingLegGeometryIndex: Int, |
112 | | - ): JsonElement { |
113 | | - if (!notification.isJsonObject) { |
114 | | - return notification |
115 | | - } |
116 | | - |
117 | | - val notificationObject = notification.asJsonObject |
118 | | - val geometryIndex = notificationObject.get("geometry_index")?.asInt |
119 | | - |
120 | | - if (geometryIndex != null) { |
121 | | - val adjustedNotification = notificationObject.deepCopy() |
122 | | - adjustedNotification.addProperty( |
123 | | - "geometry_index", |
124 | | - startingLegGeometryIndex + geometryIndex, |
125 | | - ) |
126 | | - return adjustedNotification |
127 | | - } |
128 | | - |
129 | | - return notification |
130 | | - } |
131 | | - |
132 | | - private fun JsonElement.getGeometryIndex(): Int? { |
133 | | - return if (isJsonObject) { |
134 | | - asJsonObject.get("geometry_index")?.asInt |
135 | | - } else { |
136 | | - null |
137 | | - } |
| 101 | + ): Notification { |
| 102 | + return notification.toBuilder().apply { |
| 103 | + notification.geometryIndex()?.let { |
| 104 | + geometryIndex(it + startingLegGeometryIndex) |
| 105 | + } |
| 106 | + notification.geometryIndexStart()?.let { |
| 107 | + geometryIndexStart(it + startingLegGeometryIndex) |
| 108 | + } |
| 109 | + notification.geometryIndexEnd()?.let { |
| 110 | + geometryIndexEnd(it + startingLegGeometryIndex) |
| 111 | + } |
| 112 | + }.build() |
138 | 113 | } |
139 | 114 |
|
140 | | - /** |
141 | | - * Determines if a notification should be treated as dynamic (refreshable) |
142 | | - * based on the refresh_type field |
143 | | - */ |
144 | | - private fun JsonElement.isDynamicNotification(): Boolean { |
145 | | - if (!isJsonObject) return false |
146 | | - |
147 | | - val refreshType = asJsonObject.get("refresh_type")?.asJsonPrimitive?.asString |
148 | | - return refreshType == DYNAMIC |
149 | | - } |
| 115 | + private val Notification.isDynamic: Boolean |
| 116 | + get() = refreshType() == NOTIFICATION_REFRESH_TYPE_DYNAMIC |
150 | 117 | } |
0 commit comments