feat: basic stop markers on route

This commit is contained in:
LavaDesu 2025-04-29 22:58:26 +10:00
parent 6a5a9b4974
commit 67f18afc01
Signed by: cilly
GPG key ID: 6500251E087653C9
5 changed files with 108 additions and 6 deletions

View file

@ -2,17 +2,23 @@ package moe.lava.banksia.native.maps
import android.Manifest
import android.content.pm.PackageManager
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.add
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
@ -28,10 +34,12 @@ import com.google.maps.android.compose.ComposeMapColorScheme
import com.google.maps.android.compose.DefaultMapProperties
import com.google.maps.android.compose.DefaultMapUiSettings
import com.google.maps.android.compose.GoogleMap
import com.google.maps.android.compose.MarkerComposable
import com.google.maps.android.compose.Polyline
import com.google.maps.android.compose.rememberCameraPositionState
import com.google.maps.android.compose.rememberMarkerState
import moe.lava.banksia.R
import moe.lava.banksia.native.BanksiaTheme
fun Point.toLatLng(): LatLng = LatLng(this.lat, this.lng)
@ -97,12 +105,25 @@ actual fun Maps(
),
contentPadding = WindowInsets.safeDrawing.add(extInsets).asPaddingValues()
) {
// [TODO]: Slight lag when routes with many stops such as the 901 bus is set
for (marker in markers) {
Marker(
name = marker.name,
onClick = marker.onClick
val state = rememberMarkerState()
state.position = marker.point.toLatLng()
MarkerComposable(
keys = arrayOf(marker.colour),
state = state,
title = marker.name,
onClick = { marker.onClick() }
) {
Box(
modifier = Modifier
.size(12.dp)
.clip(CircleShape)
.background(BanksiaTheme.colors.surface)
.border(2.dp, marker.colour, CircleShape)
)
}
}
for (polyline in polylines) {
Polyline(
points = polyline.points.map { it.toLatLng() },

View file

@ -37,9 +37,12 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import moe.lava.banksia.api.ptv.PtvService
import moe.lava.banksia.api.ptv.structures.PtvRoute
import moe.lava.banksia.api.ptv.structures.PtvStop
import moe.lava.banksia.api.ptv.structures.getProperties
import moe.lava.banksia.native.BanksiaTheme
import moe.lava.banksia.native.maps.Maps
import moe.lava.banksia.native.maps.Marker
import moe.lava.banksia.native.maps.MarkerType
import moe.lava.banksia.native.maps.Point
import moe.lava.banksia.native.maps.Polyline
import moe.lava.banksia.native.maps.getScreenHeight
@ -147,6 +150,9 @@ fun App() {
var peekHeight by remember { mutableStateOf(128.dp) }
var peekHeightMultiplier by remember { mutableFloatStateOf(1F) }
var markers by remember { mutableStateOf(listOf<Marker>()) }
LaunchedEffect(route) { route?.let { markers = buildStops(ptvService, it) {} } }
BanksiaTheme {
BottomSheetScaffold(
scaffoldState = scaffoldState,
@ -160,6 +166,7 @@ fun App() {
newCameraPosition = newCameraPosition,
cameraPositionUpdated = { newCameraPosition = null },
extInsets = WindowInsets(top = with(LocalDensity.current) { 56.dp.roundToPx() }, bottom = extInsets),
markers = markers,
polylines = polylines,
)
Searcher(
@ -208,3 +215,37 @@ fun App() {
}
}
}
suspend fun buildStops(
ptvService: PtvService,
route: PtvRoute,
launchInfoPanel: (PtvStop) -> Unit,
): List<Marker> {
var stops = ptvService.stopsByRoute(route.routeId, route.routeType)
var res = mutableListOf<Marker>()
val colour = route.routeType.getProperties().colour
for (stop in stops) {
if (stop.stopLatitude != null && stop.stopLongitude != null) {
val pos = Point(stop.stopLatitude!!, stop.stopLongitude!!)
var name = stop.stopName;
if (name.endsWith(" Station"))
name = name.replace(" Station", "")
val marker = Marker(
name = name,
point = pos,
type = MarkerType.GENERIC_STOP,
colour = colour,
onClick = {
launchInfoPanel(stop)
false
}
)
res.add(marker)
}
}
return res
}

View file

@ -6,7 +6,16 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
data class Marker(val name: String, val onClick: () -> Boolean)
enum class MarkerType {
GENERIC_STOP,
}
data class Marker(
val point: Point,
val name: String,
val type: MarkerType,
val colour: Color,
val onClick: () -> Boolean
)
data class Point(val lat: Double, val lng: Double)
data class Polyline(val points: List<Point>, val colour: Color)

View file

@ -14,6 +14,8 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import moe.lava.banksia.Constants
import moe.lava.banksia.api.ptv.structures.PtvRoute
import moe.lava.banksia.api.ptv.structures.PtvRouteType
import moe.lava.banksia.api.ptv.structures.PtvStop
import moe.lava.banksia.log
import okio.ByteString.Companion.encodeUtf8
@ -22,6 +24,9 @@ object Responses {
data class PtvRouteResponse(val route: PtvRoute)
@Serializable
data class PtvRoutesResponse(val routes: List<PtvRoute>)
@Serializable
data class PtvStopsResponse(val stops: List<PtvStop>)
}
class PtvService {
@ -61,4 +66,17 @@ class PtvService {
val response: Responses.PtvRoutesResponse = client.get("routes").body()
return response.routes
}
suspend fun stopsByRoute(routeId: Int, routeType: PtvRouteType): List<PtvStop> {
val response: Responses.PtvStopsResponse = client.get("stops/route") {
url {
appendPathSegments(
routeId.toString(),
"route_type",
routeType.ordinal.toString()
)
}
}.body()
return response.stops
}
}

View file

@ -0,0 +1,13 @@
package moe.lava.banksia.api.ptv.structures
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class PtvStop(
@SerialName("stop_id") val stopId: Int,
@SerialName("stop_name") val stopName: String,
@SerialName("stop_latitude") val stopLatitude: Double?,
@SerialName("stop_longitude") val stopLongitude: Double?,
@SerialName("route_type") val routeType: PtvRouteType,
)