Skip to content

Commit 011fd1f

Browse files
authored
ktfmt fixups (#902)
* Standardize dev and CI workflows with Just * Fix broken ktfmt setup * fallout: deferred formatting
1 parent b98239c commit 011fd1f

126 files changed

Lines changed: 1711 additions & 1332 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

android/build.gradle

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import com.ncorti.ktfmt.gradle.tasks.KtfmtCheckTask
2+
import com.ncorti.ktfmt.gradle.tasks.KtfmtFormatTask
13
import org.gradle.api.Project
24
import org.gradle.process.ExecOperations
35

@@ -31,3 +33,26 @@ allprojects {
3133
group = "com.stadiamaps.ferrostar"
3234
version = "0.50.0"
3335
}
36+
37+
// ktfmt-gradle 0.26 gates its Android source-set discovery on the `kotlin-android` plugin
38+
// (see KtfmtPlugin.kt -> project.plugins.withId("kotlin-android")).
39+
// AGP 9's built-in Kotlin support replaces that plugin and forbids applying it,
40+
// so the aggregate ktfmtCheck/ktfmtFormat tasks end up with no per-source-set sub-tasks
41+
// and silently no-op.
42+
// Until ktfmt-gradle ships AGP-9-aware discovery, wire the tasks ourselves.
43+
subprojects { sp ->
44+
sp.plugins.withId('com.ncorti.ktfmt.gradle') {
45+
def ktSources = sp.fileTree('src') {
46+
include '**/*.kt'
47+
exclude '**/generated/**'
48+
}
49+
def checkSources = sp.tasks.register('ktfmtCheckSources', KtfmtCheckTask) {
50+
source = ktSources
51+
}
52+
def formatSources = sp.tasks.register('ktfmtFormatSources', KtfmtFormatTask) {
53+
source = ktSources
54+
}
55+
sp.tasks.named('ktfmtCheck').configure { dependsOn checkSources }
56+
sp.tasks.named('ktfmtFormat').configure { dependsOn formatSources }
57+
}
58+
}

android/car-app/src/main/java/com/stadiamaps/ferrostar/car/app/intent/NavigationDestination.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.stadiamaps.ferrostar.car.app.intent
22

33
import android.location.Location
4-
import uniffi.ferrostar.GeographicCoordinate
54

65
/**
76
* A parsed navigation destination from an external intent.
@@ -17,7 +16,7 @@ import uniffi.ferrostar.GeographicCoordinate
1716
data class NavigationDestination(
1817
val latitude: Double?,
1918
val longitude: Double?,
20-
val query: String?
19+
val query: String?,
2120
) {
2221
/** The destination as a [Location], or null if only a query is available. */
2322
val location: Location?

android/car-app/src/main/java/com/stadiamaps/ferrostar/car/app/intent/NavigationIntentParser.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ open class NavigationIntentParser {
3232
"geo" ->
3333
parseGeoSsp(
3434
coordString = uri.schemeSpecificPart?.substringBefore('?').orEmpty(),
35-
query = uri.getQueryParameter("q"))
36-
"google.navigation" ->
37-
uri.getQueryParameter("q")?.let { parseGoogleNavigationSsp(it) }
35+
query = uri.getQueryParameter("q"),
36+
)
37+
"google.navigation" -> uri.getQueryParameter("q")?.let { parseGoogleNavigationSsp(it) }
3838
else -> null
3939
}
4040

android/car-app/src/main/java/com/stadiamaps/ferrostar/car/app/navigation/NavigationManagerBridge.kt

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import android.content.Context
44
import android.util.Log
55
import androidx.car.app.navigation.NavigationManager
66
import androidx.car.app.navigation.NavigationManagerCallback
7-
import androidx.car.app.navigation.model.Destination
8-
import androidx.lifecycle.Lifecycle
97
import com.stadiamaps.ferrostar.car.app.template.models.FerrostarTrip
108
import com.stadiamaps.ferrostar.core.NavigationViewModel
119
import kotlinx.coroutines.CoroutineScope
@@ -25,12 +23,13 @@ import uniffi.ferrostar.DrivingSide
2523
* @param context The context used to resolve maneuver icon drawables.
2624
* @param notificationManager Optional notification manager for HUN updates (NF-3).
2725
* @param viewModel The Ferrostar NavigationViewModel to observe.
28-
* @param backupDrivingSide Driving side for maneuver mapping. Defaults to RIGHT. This is only necessary if your routing server does not provide driving side.
26+
* @param backupDrivingSide Driving side for maneuver mapping. Defaults to RIGHT. This is only
27+
* necessary if your routing server does not provide driving side.
2928
* @param onStopNavigation Called when the head unit requests navigation stop.
3029
* @param onAutoDriveEnabled Enables simulation when called (NF-7). Optional.
3130
* @param isCarForeground Returns true when the car app screen is visible to the user. When true,
32-
* turn-by-turn notifications are suppressed since the screen itself shows the guidance. Pass
33-
* `{ lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) }` from your [Screen].
31+
* turn-by-turn notifications are suppressed since the screen itself shows the guidance. Pass `{
32+
* lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) }` from your [Screen].
3433
*/
3534
class NavigationManagerBridge(
3635
private val navigationManager: NavigationManager,
@@ -40,7 +39,7 @@ class NavigationManagerBridge(
4039
private val backupDrivingSide: DrivingSide = DrivingSide.RIGHT,
4140
private val onStopNavigation: () -> Unit,
4241
private val onAutoDriveEnabled: (() -> Unit)? = null,
43-
private val isCarForeground: () -> Boolean = { false }
42+
private val isCarForeground: () -> Boolean = { false },
4443
) {
4544

4645
private var tripJob: Job? = null
@@ -63,7 +62,8 @@ class NavigationManagerBridge(
6362
override fun onAutoDriveEnabled() {
6463
this@NavigationManagerBridge.onAutoDriveEnabled?.invoke()
6564
}
66-
})
65+
}
66+
)
6767

6868
// Trip lifecycle and updateTrip on every state change.
6969
tripJob =
@@ -103,9 +103,7 @@ class NavigationManagerBridge(
103103
// Notification flow: emits once per instruction trigger zone entry.
104104
notificationJob =
105105
viewModel.navigationUiState
106-
.mapNotNull { state ->
107-
state.spokenInstruction
108-
}
106+
.mapNotNull { state -> state.spokenInstruction }
109107
.distinctUntilChanged { old, new ->
110108
// Only emit if the instruction text has changed.
111109
// This is the core scheduling logic that emits a new instruction

android/car-app/src/main/java/com/stadiamaps/ferrostar/car/app/navigation/TurnByTurnNotificationManager.kt

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,14 @@ class TurnByTurnNotificationManager(
3030
private val channelId: String = DEFAULT_CHANNEL_ID,
3131
private val notificationId: Int = DEFAULT_NOTIFICATION_ID,
3232
@DrawableRes private val smallIconRes: Int,
33-
private val contentIntent: PendingIntent? = null
33+
private val contentIntent: PendingIntent? = null,
3434
) {
3535

3636
private val notificationManager = NotificationManagerCompat.from(context)
3737

3838
init {
3939
val channel =
40-
NotificationChannel(
41-
channelId, "Navigation",
42-
NotificationManager.IMPORTANCE_HIGH
43-
).apply {
40+
NotificationChannel(channelId, "Navigation", NotificationManager.IMPORTANCE_HIGH).apply {
4441
description = context.getString(R.string.notification_description)
4542
}
4643
notificationManager.createNotificationChannel(channel)
@@ -58,11 +55,7 @@ class TurnByTurnNotificationManager(
5855
.extend(
5956
CarAppExtender.Builder()
6057
.setContentTitle(instruction.text)
61-
.apply {
62-
contentIntent?.let {
63-
setContentIntent(it)
64-
}
65-
}
58+
.apply { contentIntent?.let { setContentIntent(it) } }
6659
.setImportance(NotificationManager.IMPORTANCE_HIGH)
6760
.build()
6861
)

android/car-app/src/main/java/com/stadiamaps/ferrostar/car/app/template/NavigationTemplateBuilder.kt

Lines changed: 107 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -13,136 +13,114 @@ import com.stadiamaps.ferrostar.core.extensions.progress
1313
import uniffi.ferrostar.DrivingSide
1414
import uniffi.ferrostar.TripState
1515

16-
class NavigationTemplateBuilder(
17-
private val carContext: CarContext
18-
) {
19-
private val carIcons = InterfaceCarIcons(carContext)
20-
private var tripState: TripState? = null
21-
private var backupDrivingSide: DrivingSide = DrivingSide.RIGHT
22-
23-
private var onStopTapped: (() -> Unit)? = null
24-
25-
private var isMuted: Boolean = false
26-
private var onMuteTapped: (() -> Unit)? = null
27-
28-
private var onZoomInTapped: (() -> Unit)? = null
29-
30-
private var onZoomOutTapped: (() -> Unit)? = null
31-
32-
private var cameraIsCenteredOnUser: Boolean = true
33-
private var onCycleCameraTapped: (() -> Unit)? = null
34-
35-
fun setTripState(tripState: TripState?): NavigationTemplateBuilder {
36-
this.tripState = tripState
37-
return this
38-
}
39-
40-
fun setBackupDrivingSide(drivingSide: DrivingSide): NavigationTemplateBuilder {
41-
this.backupDrivingSide = drivingSide
42-
return this
43-
}
44-
45-
fun setOnStopNavigation(onStopTapped: () -> Unit): NavigationTemplateBuilder {
46-
this.onStopTapped = onStopTapped
47-
return this
48-
}
49-
50-
fun setOnMute(
51-
isMuted: Boolean?,
52-
onMuteTapped: () -> Unit
53-
): NavigationTemplateBuilder {
54-
this.isMuted = isMuted ?: false
55-
this.onMuteTapped = onMuteTapped
56-
return this
57-
}
58-
59-
fun setOnZoom(
60-
onZoomInTapped: () -> Unit,
61-
onZoomOutTapped: () -> Unit
62-
): NavigationTemplateBuilder {
63-
this.onZoomInTapped = onZoomInTapped
64-
this.onZoomOutTapped = onZoomOutTapped
65-
return this
66-
}
67-
68-
fun setOnCycleCamera(
69-
cameraIsCenteredOnUser: Boolean?,
70-
onCycleCameraTapped: () -> Unit
71-
): NavigationTemplateBuilder {
72-
this.cameraIsCenteredOnUser = cameraIsCenteredOnUser ?: true
73-
this.onCycleCameraTapped = onCycleCameraTapped
74-
return this
75-
}
76-
77-
fun build(): Template =
78-
NavigationTemplate.Builder()
79-
.setActionStrip(buildActionStrip())
80-
.setMapActionStrip(buildMapActionStrip())
81-
.apply {
82-
tripState?.let { state ->
83-
val routingInfo = FerrostarRoutingInfo.Builder(carContext)
84-
.setTripState(state)
85-
.build()
86-
87-
routingInfo?.let { setNavigationInfo(it) }
88-
89-
state.progress()?.let {
90-
setDestinationTravelEstimate(it.toCarTravelEstimate())
91-
}
92-
}
16+
class NavigationTemplateBuilder(private val carContext: CarContext) {
17+
private val carIcons = InterfaceCarIcons(carContext)
18+
private var tripState: TripState? = null
19+
private var backupDrivingSide: DrivingSide = DrivingSide.RIGHT
20+
21+
private var onStopTapped: (() -> Unit)? = null
22+
23+
private var isMuted: Boolean = false
24+
private var onMuteTapped: (() -> Unit)? = null
25+
26+
private var onZoomInTapped: (() -> Unit)? = null
27+
28+
private var onZoomOutTapped: (() -> Unit)? = null
29+
30+
private var cameraIsCenteredOnUser: Boolean = true
31+
private var onCycleCameraTapped: (() -> Unit)? = null
32+
33+
fun setTripState(tripState: TripState?): NavigationTemplateBuilder {
34+
this.tripState = tripState
35+
return this
36+
}
37+
38+
fun setBackupDrivingSide(drivingSide: DrivingSide): NavigationTemplateBuilder {
39+
this.backupDrivingSide = drivingSide
40+
return this
41+
}
42+
43+
fun setOnStopNavigation(onStopTapped: () -> Unit): NavigationTemplateBuilder {
44+
this.onStopTapped = onStopTapped
45+
return this
46+
}
47+
48+
fun setOnMute(isMuted: Boolean?, onMuteTapped: () -> Unit): NavigationTemplateBuilder {
49+
this.isMuted = isMuted ?: false
50+
this.onMuteTapped = onMuteTapped
51+
return this
52+
}
53+
54+
fun setOnZoom(
55+
onZoomInTapped: () -> Unit,
56+
onZoomOutTapped: () -> Unit,
57+
): NavigationTemplateBuilder {
58+
this.onZoomInTapped = onZoomInTapped
59+
this.onZoomOutTapped = onZoomOutTapped
60+
return this
61+
}
62+
63+
fun setOnCycleCamera(
64+
cameraIsCenteredOnUser: Boolean?,
65+
onCycleCameraTapped: () -> Unit,
66+
): NavigationTemplateBuilder {
67+
this.cameraIsCenteredOnUser = cameraIsCenteredOnUser ?: true
68+
this.onCycleCameraTapped = onCycleCameraTapped
69+
return this
70+
}
71+
72+
fun build(): Template =
73+
NavigationTemplate.Builder()
74+
.setActionStrip(buildActionStrip())
75+
.setMapActionStrip(buildMapActionStrip())
76+
.apply {
77+
tripState?.let { state ->
78+
val routingInfo = FerrostarRoutingInfo.Builder(carContext).setTripState(state).build()
79+
80+
routingInfo?.let { setNavigationInfo(it) }
81+
82+
state.progress()?.let { setDestinationTravelEstimate(it.toCarTravelEstimate()) }
9383
}
94-
.build()
95-
96-
private fun buildActionStrip(): ActionStrip {
97-
return ActionStrip.Builder()
98-
.apply {
99-
onStopTapped?.let {
100-
addAction(
101-
Action.Builder()
102-
.setTitle(carContext.getString(R.string.stop_nav))
103-
.setOnClickListener(it)
104-
.build()
105-
)
106-
}
84+
}
85+
.build()
86+
87+
private fun buildActionStrip(): ActionStrip {
88+
return ActionStrip.Builder()
89+
.apply {
90+
onStopTapped?.let {
91+
addAction(
92+
Action.Builder()
93+
.setTitle(carContext.getString(R.string.stop_nav))
94+
.setOnClickListener(it)
95+
.build()
96+
)
97+
}
98+
}
99+
.build()
100+
}
101+
102+
private fun buildMapActionStrip(): ActionStrip =
103+
ActionStrip.Builder()
104+
.apply {
105+
onMuteTapped?.let {
106+
addAction(
107+
Action.Builder().setIcon(carIcons.mute(isMuted)).setOnClickListener(it).build()
108+
)
107109
}
108-
.build()
109-
}
110-
111-
private fun buildMapActionStrip(): ActionStrip =
112-
ActionStrip.Builder()
113-
.apply {
114-
onMuteTapped?.let {
115-
addAction(
116-
Action.Builder()
117-
.setIcon(carIcons.mute(isMuted))
118-
.setOnClickListener(it)
119-
.build()
120-
)
121-
}
122-
onZoomInTapped?.let {
123-
addAction(
124-
Action.Builder()
125-
.setIcon(carIcons.add)
126-
.setOnClickListener(it)
127-
.build()
128-
)
129-
}
130-
onZoomOutTapped?.let {
131-
addAction(
132-
Action.Builder()
133-
.setIcon(carIcons.remove)
134-
.setOnClickListener(it)
135-
.build()
136-
)
137-
}
138-
onCycleCameraTapped?.let {
139-
addAction(
140-
Action.Builder()
141-
.setIcon(carIcons.camera(cameraIsCenteredOnUser))
142-
.setOnClickListener(it)
143-
.build()
144-
)
145-
}
110+
onZoomInTapped?.let {
111+
addAction(Action.Builder().setIcon(carIcons.add).setOnClickListener(it).build())
112+
}
113+
onZoomOutTapped?.let {
114+
addAction(Action.Builder().setIcon(carIcons.remove).setOnClickListener(it).build())
115+
}
116+
onCycleCameraTapped?.let {
117+
addAction(
118+
Action.Builder()
119+
.setIcon(carIcons.camera(cameraIsCenteredOnUser))
120+
.setOnClickListener(it)
121+
.build()
122+
)
146123
}
147-
.build()
124+
}
125+
.build()
148126
}

0 commit comments

Comments
 (0)