feat: implement route type and icons

This commit is contained in:
LavaDesu 2025-04-15 14:09:46 +10:00
parent 3c0eb906cc
commit 4cd160cc47
Signed by: cilly
GPG key ID: 6500251E087653C9
13 changed files with 200 additions and 3 deletions

View file

@ -0,0 +1,14 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:gravity="fill"
android:drawable="@drawable/bus_background"
/>
<item
android:gravity="center"
android:drawable="@drawable/bus_icon"
android:top="5dp"
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
/>
</layer-list>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF8200"
android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="#FFFFFF" android:pathData="M4,16c0,0.88 0.39,1.67 1,2.22L5,20c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-1h8v1c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-1.78c0.61,-0.55 1,-1.34 1,-2.22L20,6c0,-3.5 -3.58,-4 -8,-4s-8,0.5 -8,4v10zM7.5,17c-0.83,0 -1.5,-0.67 -1.5,-1.5S6.67,14 7.5,14s1.5,0.67 1.5,1.5S8.33,17 7.5,17zM16.5,17c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM18,11L6,11L6,6h12v5z"/>
</vector>

View file

@ -0,0 +1,14 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:gravity="fill"
android:drawable="@drawable/train_background"
/>
<item
android:gravity="center"
android:drawable="@drawable/train_icon"
android:top="5dp"
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
/>
</layer-list>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#0072CE"
android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="#FFFFFF" android:pathData="M12,2c-4,0 -8,0.5 -8,4v9.5C4,17.43 5.57,19 7.5,19L6,20.5v0.5h2.23l2,-2L14,19l2,2h2v-0.5L16.5,19c1.93,0 3.5,-1.57 3.5,-3.5L20,6c0,-3.5 -3.58,-4 -8,-4zM7.5,17c-0.83,0 -1.5,-0.67 -1.5,-1.5S6.67,14 7.5,14s1.5,0.67 1.5,1.5S8.33,17 7.5,17zM11,10L6,10L6,6h5v4zM13,10L13,6h5v4h-5zM16.5,17c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z"/>
</vector>

View file

@ -0,0 +1,14 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:gravity="fill"
android:drawable="@drawable/tram_background"
/>
<item
android:gravity="center"
android:drawable="@drawable/tram_icon"
android:top="5dp"
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
/>
</layer-list>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#78BE20"
android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="#FFFFFF" android:pathData="M19,16.94L19,8.5c0,-2.79 -2.61,-3.4 -6.01,-3.49l0.76,-1.51L17,3.5L17,2L7,2v1.5h4.75l-0.76,1.52C7.86,5.11 5,5.73 5,8.5v8.44c0,1.45 1.19,2.66 2.59,2.97L6,21.5v0.5h2.23l2,-2L14,20l2,2h2v-0.5L16.5,20h-0.08c1.69,0 2.58,-1.37 2.58,-3.06zM12,18.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM17,14L7,14L7,9h10v5z"/>
</vector>

View file

@ -0,0 +1,56 @@
package moe.lava.banksia.api.ptv
import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import moe.lava.banksia.resources.Res
import moe.lava.banksia.resources.bus
import moe.lava.banksia.resources.bus_background
import moe.lava.banksia.resources.bus_icon
import moe.lava.banksia.resources.train
import moe.lava.banksia.resources.train_background
import moe.lava.banksia.resources.train_icon
import moe.lava.banksia.resources.tram
import moe.lava.banksia.resources.tram_background
import moe.lava.banksia.resources.tram_icon
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.painterResource
data class RouteTypeProperties(
val colour: Color,
val drawable: DrawableResource,
val background: DrawableResource,
val icon: DrawableResource,
)
fun RouteType.getProperties(): RouteTypeProperties {
val colour = when (this) {
RouteType.TRAIN -> Color(0xFF0072CE)
RouteType.TRAM -> Color(0xFF78BE20)
RouteType.BUS, RouteType.NIGHT_BUS -> Color(0xFFFF8200)
RouteType.VLINE -> Color(0xFF8F1A95)
}
val (drawable, background, icon) = when (this) {
RouteType.TRAM -> Triple(
Res.drawable.tram, Res.drawable.tram_background, Res.drawable.tram_icon)
RouteType.TRAIN, RouteType.VLINE -> Triple(
Res.drawable.train, Res.drawable.train_background, Res.drawable.train_icon)
RouteType.BUS, RouteType.NIGHT_BUS -> Triple(
Res.drawable.bus, Res.drawable.bus_background, Res.drawable.bus_icon)
}
return RouteTypeProperties(colour, drawable, background, icon)
}
@Composable
fun RouteType.ComposableIcon() {
val properties = this.getProperties()
Image(
painter = painterResource(properties.icon),
contentDescription = null,
modifier = Modifier
.drawBehind {
drawCircle(properties.colour, radius = (this.size.minDimension + 10.dp.toPx()) / 2f)
}
)
}

View file

@ -30,6 +30,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import moe.lava.banksia.api.ptv.ComposableIcon
import moe.lava.banksia.api.ptv.PtvService
import moe.lava.banksia.api.ptv.Route
@ -58,7 +59,7 @@ fun Searcher(
val localRoutes = ptvService.routes()
routes = localRoutes.sortedWith(
compareBy(
// { it.routeType.ordinal },
{ it.gtfsSubType()?.ordinal },
{ it.routeNumber.toIntOrNull() },
{ it.routeName }
)
@ -104,7 +105,7 @@ fun Searcher(
Text(route.routeName)
}
},
// leadingContent = { route.route_type.ComposableIcon() },
leadingContent = { route.routeType.ComposableIcon() },
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
modifier = Modifier
.fillMaxWidth()

View file

@ -18,12 +18,34 @@ import moe.lava.banksia.Constants
import moe.lava.banksia.log
import okio.ByteString.Companion.encodeUtf8
// Ordinals used for sorting in searcher
enum class GtfsSubType(val value: Int) {
MetroTrain(2),
MetroTram(3),
MetroBus(4),
RegionalTrain(1),
RegionalCoach(5),
RegionalBus(6),
SkyBus(11),
Interstate(10),
}
@Serializable
data class Route(
@SerialName("route_type") val routeType: RouteType,
@SerialName("route_id") val routeId: Int,
@SerialName("route_number") val routeNumber: String,
@SerialName("route_name") val routeName: String,
)
@SerialName("route_gtfs_id") val routeGtfsId: String,
) {
fun gtfsSubType(): GtfsSubType? {
GtfsSubType.entries.forEach {
if (routeGtfsId.startsWith(it.value.toString()))
return it
}
return null
}
}
@Serializable
data class RouteResponse(val routes: List<Route>)

View file

@ -0,0 +1,34 @@
package moe.lava.banksia.api.ptv
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
private object RouteTypeSerializer : KSerializer<RouteType> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(RouteType::class.qualifiedName!!,
PrimitiveKind.INT)
override fun serialize(encoder: Encoder, value: RouteType) {
encoder.encodeInt(value.ordinal)
}
override fun deserialize(decoder: Decoder): RouteType {
val index = decoder.decodeInt()
return RouteType.entries[index]
}
override fun toString(): String = "EnumOrdinalSerializer<${descriptor.serialName}>"
}
@Serializable(with = RouteTypeSerializer::class)
enum class RouteType {
TRAIN,
TRAM,
BUS,
VLINE,
NIGHT_BUS,
}