Bimba.git

commit 10eb297d07aace2818807e82d4efa02c90898cec

Author: Adam Evyčędo <git@apiote.xyz>

fix continue button in server choosing

%!v(PANIC=String method: strings: negative Repeat count)


diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/Interfaces.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/Interfaces.kt
index 17e5533d91f6f911a98be67bc0613f21e7d4541d..424e7e04e73911f263540abf7f53617cc4459bdb 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/api/Interfaces.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/Interfaces.kt
@@ -2,5 +2,7 @@ package xyz.apiote.bimba.czwek.api
 
 interface QueryableV1
 interface QueryableV2
+interface QueryableV3
 interface LocatableV1
-interface LocatableV2
\ No newline at end of file
+interface LocatableV2
+interface LocatableV3
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/Responses.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/Responses.kt
index 4946e573114915e4a9f6bfa963cbf71f2040e447..18eab3d10e2d0b467214a33c747b09b481985c05 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/api/Responses.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/Responses.kt
@@ -20,11 +20,11 @@ 	}
 }
 
 data class LineResponseDev(
-	val line: LineV1
+	val line: LineV2
 ) : LineResponse {
 	companion object {
 		fun unmarshal(stream: InputStream): LineResponseDev {
-			return LineResponseDev(LineV1.unmarshal(stream))
+			return LineResponseDev(LineV2.unmarshal(stream))
 		}
 	}
 }
@@ -55,13 +55,13 @@ }
 
 data class DeparturesResponseDev(
 	val alerts: List<AlertV1>,
-	val departures: List<DepartureV2>,
+	val departures: List<DepartureV3>,
 	val stop: StopV2
 ) : DeparturesResponse {
 	companion object {
 		fun unmarshal(stream: InputStream): DeparturesResponseDev {
 			val alerts = mutableListOf<AlertV1>()
-			val departures = mutableListOf<DepartureV2>()
+			val departures = mutableListOf<DepartureV3>()
 
 			val reader = Reader(stream)
 			val alertsNum = reader.readUInt().toULong()
@@ -71,7 +71,7 @@ 				alerts.add(alert)
 			}
 			val departuresNum = reader.readUInt().toULong()
 			for (i in 0UL until departuresNum) {
-				val departure = DepartureV2.unmarshal(stream)
+				val departure = DepartureV3.unmarshal(stream)
 				departures.add(departure)
 			}
 
@@ -148,10 +148,10 @@ 		}
 	}
 }
 
-data class QueryablesResponseDev(val queryables: List<QueryableV2>) : QueryablesResponse {
+data class QueryablesResponseDev(val queryables: List<QueryableV3>) : QueryablesResponse {
 	companion object {
 		fun unmarshal(stream: InputStream): QueryablesResponseDev {
-			val queryables = mutableListOf<QueryableV2>()
+			val queryables = mutableListOf<QueryableV3>()
 			val reader = Reader(stream)
 			val n = reader.readUInt().toULong()
 			for (i in 0UL until n) {
@@ -161,11 +161,11 @@ 						queryables.add(StopV2.unmarshal(stream))
 					}
 
 					1UL -> {
-						queryables.add(LineV1.unmarshal(stream))
+						queryables.add(LineV2.unmarshal(stream))
 					}
 
 					else -> {
-						throw UnknownResourceVersionException("Queryable/$r", 1u)
+						throw UnknownResourceVersionException("Queryable/$r", 0u)
 					}
 				}
 			}
@@ -213,7 +213,7 @@ 						queryables.add(LineV1.unmarshal(stream))
 					}
 
 					else -> {
-						throw UnknownResourceVersionException("Queryable/$r", 1u)
+						throw UnknownResourceVersionException("Queryable/$r", 2u)
 					}
 				}
 			}
@@ -281,10 +281,10 @@ 		}
 	}
 }
 
-data class LocatablesResponseDev(val locatables: List<LocatableV2>) : LocatablesResponse {
+data class LocatablesResponseDev(val locatables: List<LocatableV3>) : LocatablesResponse {
 	companion object {
 		fun unmarshal(stream: InputStream): LocatablesResponseDev {
-			val locatables = mutableListOf<LocatableV2>()
+			val locatables = mutableListOf<LocatableV3>()
 			val reader = Reader(stream)
 			val n = reader.readUInt().toULong()
 			for (i in 0UL until n) {
@@ -294,11 +294,11 @@ 						locatables.add(StopV2.unmarshal(stream))
 					}
 
 					1UL -> {
-						locatables.add(VehicleV2.unmarshal(stream))
+						locatables.add(VehicleV3.unmarshal(stream))
 					}
 
 					else -> {
-						throw UnknownResourceVersionException("Locatable/$r", 1u)
+						throw UnknownResourceVersionException("Locatable/$r", 0u)
 					}
 				}
 			}
@@ -343,7 +343,7 @@ 			for (i in 0UL until n) {
 				when (val r = reader.readUInt().toULong()) {
 					0UL -> locatables.add(StopV2.unmarshal(stream))
 					1UL -> locatables.add(VehicleV2.unmarshal(stream))
-					else -> throw UnknownResourceVersionException("Locatable/$r", 1u)
+					else -> throw UnknownResourceVersionException("Locatable/$r", 2u)
 				}
 			}
 			return LocatablesResponseV2(locatables)




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt
index 25298232b91abb5e997c6d68aab5d87aac285a51..d5f464c24cfb86ce7970768c513624b7a9d16df1 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt
@@ -326,6 +326,33 @@ 		}
 	}
 }
 
+data class VehicleV3(
+	val ID: String,
+	val Position: PositionV1,
+	val Capabilities: UShort,
+	val Speed: Float,
+	val Line: LineStubV3,
+	val Headsign: String,
+	val CongestionLevel: CongestionLevelV1,
+	val OccupancyStatus: OccupancyStatusV1
+) : LocatableV3 {
+	companion object {
+		fun unmarshal(stream: InputStream): VehicleV3 {
+			val reader = Reader(stream)
+			return VehicleV3(
+				reader.readString(),
+				PositionV1.unmarshal(stream),
+				reader.readU16(),
+				reader.readFloat32(),
+				LineStubV3.unmarshal(stream),
+				reader.readString(),
+				CongestionLevelV1.of(reader.readUInt().toULong().toUInt()),
+				OccupancyStatusV1.of(reader.readUInt().toULong().toUInt())
+			)
+		}
+	}
+}
+
 data class LineStubV1(
 	val name: String, val kind: LineTypeV1, val colour: ColourV1
 ) {
@@ -356,6 +383,21 @@ 		}
 	}
 }
 
+data class LineStubV3(
+	val name: String, val kind: LineTypeV3, val colour: ColourV1
+) {
+	companion object {
+		fun unmarshal(stream: InputStream): LineStubV3 {
+			val reader = Reader(stream)
+			return LineStubV3(
+				reader.readString(),
+				LineTypeV3.of(reader.readUInt().toULong().toUInt()),
+				ColourV1.unmarshal(stream)
+			)
+		}
+	}
+}
+
 data class DepartureV1(
 	val ID: String,
 	val time: Time,
@@ -402,6 +444,29 @@ 		}
 	}
 }
 
+data class DepartureV3(
+	val ID: String,
+	val time: Time,
+	val status: ULong,
+	val isRealtime: Boolean,
+	val vehicle: VehicleV3,
+	val boarding: UByte
+) {
+
+	companion object {
+		fun unmarshal(stream: InputStream): DepartureV3 {
+			val reader = Reader(stream)
+			val id = reader.readString()
+			val time = Time.unmarshal(stream)
+			val status = reader.readUInt().toULong()
+			val isRealtime = reader.readBoolean()
+			val vehicle = VehicleV3.unmarshal(stream)
+			val boarding = reader.readU8()
+			return DepartureV3(id, time, status, isRealtime, vehicle, boarding)
+		}
+	}
+}
+
 @Parcelize
 data class StopV2(
 	val code: String,
@@ -411,7 +476,7 @@ 	val zone: String,
 	val feedID: String,
 	val position: PositionV1,
 	val changeOptions: List<ChangeOptionV1>
-) : QueryableV2, Parcelable, LocatableV2 {
+) : QueryableV2, Parcelable, LocatableV2, QueryableV3, LocatableV3 {
 	companion object {
 		fun unmarshal(stream: InputStream): StopV2 {
 			val reader = Reader(stream)
@@ -510,6 +575,50 @@ 			)
 		}
 	}
 }
+data class LineV2(
+	val name: String,
+	val colour: ColourV1,
+	val type: LineTypeV3,
+	val feedID: String,
+	val headsigns: List<List<String>>,
+	val graphs: List<LineGraph>,
+) : QueryableV3 {
+	override fun toString(): String {
+		return "$name ($type) [$colour]\n${headsigns.map { "-> ${it.joinToString()}" }}"
+	}
+
+	companion object {
+		fun unmarshal(stream: InputStream): LineV2 {
+			val reader = Reader(stream)
+			val name = reader.readString()
+			val colour = ColourV1.unmarshal(stream)
+			val type = reader.readUInt()
+			val feedID = reader.readString()
+			var directionsNum = reader.readUInt().toULong()
+			val headsigns = (0UL until directionsNum).map {
+				val headsignsNum = reader.readUInt().toULong()
+				val headsignsDir = mutableListOf<String>()
+				for (j in 0UL until headsignsNum) {
+					headsignsDir.add(reader.readString())
+				}
+				headsignsDir
+			}
+			directionsNum = reader.readUInt().toULong()
+			val graphs = mutableListOf<LineGraph>()
+			for (i in 0UL until directionsNum) {
+				graphs.add(LineGraph.unmarshal(stream))
+			}
+			return LineV2(
+				name = name,
+				colour = colour,
+				type = LineTypeV3.of(type.toULong().toUInt()),
+				feedID = feedID,
+				headsigns = headsigns,
+				graphs = graphs
+			)
+		}
+	}
+}
 
 enum class LineTypeV1 {
 	UNKNOWN, TRAM, BUS;
@@ -536,7 +645,30 @@ 				0u -> valueOf("UNKNOWN")
 				1u -> valueOf("TRAM")
 				2u -> valueOf("BUS")
 				3u -> valueOf("TROLLEYBUS")
-				else -> throw UnknownResourceVersionException("LineType/$type", 1u)
+				else -> throw UnknownResourceVersionException("LineType/$type", 2u)
+			}
+		}
+	}
+}
+
+enum class LineTypeV3 {
+	UNKNOWN, TRAM, BUS, TROLLEYBUS, METRO, RAIL, FERRY, CABLE_TRAM, CABLE_CAR, FUNICULAR, MONORAIL;
+
+	companion object {
+		fun of(type: UInt): LineTypeV3 {
+			return when (type) {
+				0u -> valueOf("UNKNOWN")
+				1u -> valueOf("TRAM")
+				2u -> valueOf("BUS")
+				3u -> valueOf("TROLLEYBUS")
+				4u -> valueOf("METRO")
+				5u -> valueOf("RAIL")
+				6u -> valueOf("FERRY")
+				7u -> valueOf("CABLE_TRAM")
+				8u -> valueOf("CABLE_CAR")
+				9u -> valueOf("FUNICULAR")
+				10u -> valueOf("MONORAIL")
+				else -> throw UnknownResourceVersionException("LineType/$type", 3u)
 			}
 		}
 	}




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt
index c640b83234c78c51f8cf6ad09565d8e6e6c5f605..caf71e076f87e2c38c5b3b3e3b0b006cf4e9e642 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt
@@ -8,6 +8,7 @@ import xyz.apiote.bimba.czwek.api.AlertEffectV1
 import xyz.apiote.bimba.czwek.api.AlertV1
 import xyz.apiote.bimba.czwek.api.DepartureV1
 import xyz.apiote.bimba.czwek.api.DepartureV2
+import xyz.apiote.bimba.czwek.api.DepartureV3
 import xyz.apiote.bimba.czwek.api.Time
 import xyz.apiote.bimba.czwek.api.UnknownResourceVersionException
 import java.time.Instant
@@ -97,6 +98,15 @@ 		d.boarding
 	)
 
 	constructor(d: DepartureV2) : this(
+		d.ID,
+		d.time,
+		d.status,
+		d.isRealtime,
+		Vehicle(d.vehicle),
+		d.boarding
+	)
+
+	constructor(d: DepartureV3) : this(
 		d.ID,
 		d.time,
 		d.status,




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Line.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Line.kt
index 62568fdce835e8abc3e82c9ce3280d848fb1d1a1..bd9e7549d477d10549408f3485230ff659b8d48d 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Line.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Line.kt
@@ -4,6 +4,7 @@ import android.content.Context
 import android.graphics.drawable.BitmapDrawable
 import android.graphics.drawable.Drawable
 import xyz.apiote.bimba.czwek.api.LineV1
+import xyz.apiote.bimba.czwek.api.LineV2
 
 data class Line(
 	val name: String,
@@ -15,6 +16,14 @@ 	val graphs: List,
 ) : Queryable, LineAbstract {
 
 	constructor(line: LineV1) : this(
+		line.name,
+		Colour(line.colour),
+		LineType.of(line.type),
+		line.feedID,
+		line.headsigns,
+		line.graphs.map{LineGraph(it)}
+	)
+	constructor(line: LineV2) : this(
 		line.name,
 		Colour(line.colour),
 		LineType.of(line.type),




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineAbstract.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineAbstract.kt
index d3a0778b3595e3a215a478a0c7b77b0196582570..5a032e11631277e4a84e3ecfcfa4d92eadc6b030 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineAbstract.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineAbstract.kt
@@ -59,6 +59,13 @@ 		val iconID = when (type) {
 			LineType.BUS -> R.drawable.bus_black
 			LineType.TRAM -> R.drawable.tram_black
 			LineType.TROLLEYBUS -> R.drawable.trolleybus_black
+			LineType.METRO -> R.drawable.metro_black
+			LineType.RAIL -> R.drawable.train_black
+			LineType.FERRY -> R.drawable.ferry_black
+			LineType.CABLE_TRAM -> TODO()
+			LineType.CABLE_CAR -> TODO()
+			LineType.FUNICULAR -> TODO()
+			LineType.MONORAIL -> R.drawable.monorail_black
 			LineType.UNKNOWN -> R.drawable.vehicle_black
 		}
 		val icon = AppCompatResources.getDrawable(context, iconID)?.mutate()?.apply {




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineStub.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineStub.kt
index 6f9f69264310cf126b42985bf1ab8557c4ddf95b..95e95b07d7cb1ef4dcf3715b55480194129b5850 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineStub.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineStub.kt
@@ -5,10 +5,12 @@ import android.graphics.drawable.BitmapDrawable
 import android.graphics.drawable.Drawable
 import xyz.apiote.bimba.czwek.api.LineStubV1
 import xyz.apiote.bimba.czwek.api.LineStubV2
+import xyz.apiote.bimba.czwek.api.LineStubV3
 
 data class LineStub(val name: String, val kind: LineType, val colour: Colour) : LineAbstract {
 	constructor(l: LineStubV1) : this(l.name, LineType.of(l.kind), Colour(l.colour))
 	constructor(l: LineStubV2) : this(l.name, LineType.of(l.kind), Colour(l.colour))
+	constructor(l: LineStubV3) : this(l.name, LineType.of(l.kind), Colour(l.colour))
 
 	fun icon(context: Context, scale: Float = 1f): Drawable {
 		return BitmapDrawable(context.resources, super.icon(context, kind, colour, scale))




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineType.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineType.kt
index ce3c5ec6b35bdd93a154cd2f1d99b8cfaf526b19..84ed17b863b9ecf641fc66dc85d5e50eedbaa4e4 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineType.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineType.kt
@@ -2,9 +2,10 @@ package xyz.apiote.bimba.czwek.repo
 
 import xyz.apiote.bimba.czwek.api.LineTypeV1
 import xyz.apiote.bimba.czwek.api.LineTypeV2
+import xyz.apiote.bimba.czwek.api.LineTypeV3
 
 enum class LineType {
-	UNKNOWN, TRAM, BUS, TROLLEYBUS;
+	UNKNOWN, TRAM, BUS, TROLLEYBUS, METRO, RAIL, FERRY, CABLE_TRAM, CABLE_CAR, FUNICULAR, MONORAIL;
 
 	companion object {
 		fun of(t: LineTypeV1): LineType {
@@ -20,6 +21,21 @@ 				LineTypeV2.UNKNOWN -> valueOf("UNKNOWN")
 				LineTypeV2.TRAM -> valueOf("TRAM")
 				LineTypeV2.BUS -> valueOf("BUS")
 				LineTypeV2.TROLLEYBUS -> valueOf("TROLLEYBUS")
+			}
+		}
+		fun of(t: LineTypeV3): LineType {
+			return when (t) {
+				LineTypeV3.UNKNOWN -> valueOf("UNKNOWN")
+				LineTypeV3.TRAM -> valueOf("TRAM")
+				LineTypeV3.BUS -> valueOf("BUS")
+				LineTypeV3.TROLLEYBUS -> valueOf("TROLLEYBUS")
+				LineTypeV3.METRO -> valueOf("METRO")
+				LineTypeV3.RAIL -> valueOf("RAIL")
+				LineTypeV3.FERRY -> valueOf("FERRY")
+				LineTypeV3.CABLE_TRAM -> valueOf("CABLE_TRAM")
+				LineTypeV3.CABLE_CAR -> valueOf("CABLE_CAR")
+				LineTypeV3.FUNICULAR -> valueOf("FUNICULAR")
+				LineTypeV3.MONORAIL -> valueOf("MONORAIL")
 			}
 		}
 	}




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt
index 5c94740846682be05460fe8c9dce46bc21ae6228..100c4dd181f5b5324e3567b2a8b78a40b6ee3fb4 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt
@@ -13,6 +13,7 @@ import xyz.apiote.bimba.czwek.api.LineResponse
 import xyz.apiote.bimba.czwek.api.LineResponseDev
 import xyz.apiote.bimba.czwek.api.LineResponseV1
 import xyz.apiote.bimba.czwek.api.LineV1
+import xyz.apiote.bimba.czwek.api.LineV2
 import xyz.apiote.bimba.czwek.api.LocatablesResponse
 import xyz.apiote.bimba.czwek.api.LocatablesResponseDev
 import xyz.apiote.bimba.czwek.api.LocatablesResponseV1
@@ -28,6 +29,7 @@ import xyz.apiote.bimba.czwek.api.StopV2
 import xyz.apiote.bimba.czwek.api.UnknownResourceException
 import xyz.apiote.bimba.czwek.api.VehicleV1
 import xyz.apiote.bimba.czwek.api.VehicleV2
+import xyz.apiote.bimba.czwek.api.VehicleV3
 
 // todo [3.2] in Repository check if responses are BARE or HTML
 
@@ -96,7 +98,7 @@ 				withContext(Dispatchers.IO) { LocatablesResponse.unmarshal(result.stream!!) }) {
 				is LocatablesResponseDev -> response.locatables.map {
 					when (it) {
 						is StopV2 -> Stop(it)
-						is VehicleV2 -> Vehicle(it)
+						is VehicleV3 -> Vehicle(it)
 						else -> throw UnknownResourceException("locatables", it::class)
 					}
 				}
@@ -182,7 +184,7 @@ 				withContext(Dispatchers.IO) { QueryablesResponse.unmarshal(result.stream!!) }) {
 				is QueryablesResponseDev -> response.queryables.map {
 					when (it) {
 						is StopV2 -> Stop(it)
-						is LineV1 -> Line(it)
+						is LineV2 -> Line(it)
 						else -> throw UnknownResourceException("queryablesV2", it::class)
 					}
 				}




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt
index 509e4819d6b6826c07323c71425f0f1928549319..83688f33542121adac02d6064a214664d749c52d 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt
@@ -6,6 +6,7 @@ import xyz.apiote.bimba.czwek.api.CongestionLevelV1
 import xyz.apiote.bimba.czwek.api.OccupancyStatusV1
 import xyz.apiote.bimba.czwek.api.VehicleV1
 import xyz.apiote.bimba.czwek.api.VehicleV2
+import xyz.apiote.bimba.czwek.api.VehicleV3
 
 enum class CongestionLevel {
 	UNKNOWN, SMOOTH, STOP_AND_GO, SIGNIFICANT, SEVERE;
@@ -86,6 +87,17 @@ 		OccupancyStatus.of(v.OccupancyStatus)
 	)
 
 	constructor(v: VehicleV2) : this(
+		v.ID,
+		Position(v.Position),
+		v.Capabilities,
+		v.Speed,
+		LineStub(v.Line),
+		v.Headsign,
+		CongestionLevel.of(v.CongestionLevel),
+		OccupancyStatus.of(v.OccupancyStatus)
+	)
+
+	constructor(v: VehicleV3) : this(
 		v.ID,
 		Position(v.Position),
 		v.Capabilities,




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/settings/ServerChooserActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/settings/ServerChooserActivity.kt
index d1d96616c5998e2ed5f21c1da8719658f57fe9b6..7eeea11e0764d396d27c032a8d9fa211e203a82b 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/settings/ServerChooserActivity.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/settings/ServerChooserActivity.kt
@@ -152,25 +152,22 @@ 				showDialog(R.string.error, R.string.error_traffic_spec, R.drawable.error_server, null)
 				return@launch
 			}
 
-			if (isSimple) {
-				updateServer(bimba.servers[0]["url"]!!)
-				moveOn(bimba, true)
+			if (preferences.getBoolean("shibboleet", false)) {
+				val validServers = bimba.servers.filter { !it.getOrDefault("url", null).isNullOrBlank() }
+				val servers = validServers.toTypedArray()
+				MaterialAlertDialogBuilder(this@ServerChooserActivity)
+					.setTitle(R.string.choose_server)
+					.setItems(servers.map { it["description"] }.toTypedArray()) { _, i ->
+						updateServer(servers[i]["url"].toString())
+						moveOn(bimba, false)
+					}
+					.show()
 				return@launch
 			}
 
-			if (preferences.getBoolean("shibboleet", false)) {
-				val validServers = bimba.servers.filter { !it.getOrDefault("url", null).isNullOrBlank() }
-				if (validServers.size > 1) {
-					val servers = validServers.toTypedArray()
-					MaterialAlertDialogBuilder(this@ServerChooserActivity)
-						.setTitle(R.string.choose_server)
-						.setItems(servers.map { it["description"] }.toTypedArray()) { _, i ->
-							updateServer(servers[i]["url"].toString())
-							moveOn(bimba, false)
-						}
-						.show()
-				}
-			}
+			updateServer(bimba.servers[0]["url"]!!)
+			moveOn(bimba, isSimple)
+			return@launch
 		}
 	}
 




diff --git a/app/src/main/res/drawable/ferry_black.xml b/app/src/main/res/drawable/ferry_black.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ea12665e52d311dc0fea6599d786b2f871b84ce0
--- /dev/null
+++ b/app/src/main/res/drawable/ferry_black.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M20,21c-1.39,0 -2.78,-0.47 -4,-1.32 -2.44,1.71 -5.56,1.71 -8,0C6.78,20.53 5.39,21 4,21H2v2h2c1.38,0 2.74,-0.35 4,-0.99 2.52,1.29 5.48,1.29 8,0 1.26,0.65 2.62,0.99 4,0.99h2v-2h-2zM3.95,19H4c1.6,0 3.02,-0.88 4,-2 0.98,1.12 2.4,2 4,2s3.02,-0.88 4,-2c0.98,1.12 2.4,2 4,2h0.05l1.89,-6.68c0.08,-0.26 0.06,-0.54 -0.06,-0.78s-0.34,-0.42 -0.6,-0.5L20,10.62V6c0,-1.1 -0.9,-2 -2,-2h-3V1H9v3H6c-1.1,0 -2,0.9 -2,2v4.62l-1.29,0.42c-0.26,0.08 -0.48,0.26 -0.6,0.5s-0.15,0.52 -0.06,0.78L3.95,19zM6,6h12v3.97L12,8 6,9.97V6z"/>
+</vector>




diff --git a/app/src/main/res/drawable/metro_black.xml b/app/src/main/res/drawable/metro_black.xml
new file mode 100644
index 0000000000000000000000000000000000000000..774889ef23cab20a0bfa33df7b2edc650da9f98a
--- /dev/null
+++ b/app/src/main/res/drawable/metro_black.xml
@@ -0,0 +1,7 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M15.5,16m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"/>
+    <path android:fillColor="@android:color/white" android:pathData="M8.5,16m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"/>
+    <path android:fillColor="@android:color/white" android:pathData="M7.01,9h10v5h-10zM17.8,2.8C16,2.09 13.86,2 12,2c-1.86,0 -4,0.09 -5.8,0.8C3.53,3.84 2,6.05 2,8.86L2,22h20L22,8.86c0,-2.81 -1.53,-5.02 -4.2,-6.06zM18,15.88c0,1.45 -1.18,2.62 -2.63,2.62l1.13,1.12L16.5,20L15,20l-1.5,-1.5h-2.83L9.17,20L7.5,20v-0.38l1.12,-1.12C7.18,18.5 6,17.32 6,15.88L6,9c0,-2.63 3,-3 6,-3 3.32,0 6,0.38 6,3v6.88z"/>
+</vector>




diff --git a/app/src/main/res/drawable/monorail_black.xml b/app/src/main/res/drawable/monorail_black.xml
new file mode 100644
index 0000000000000000000000000000000000000000..15c01ec0e04daf1588df0368730c328327c91441
--- /dev/null
+++ b/app/src/main/res/drawable/monorail_black.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M4,15.5C4,17.43 5.57,19 7.5,19L6,20.5v0.5h12v-0.5L16.5,19c1.93,0 3.5,-1.57 3.5,-3.5L20,5c0,-3.5 -3.58,-4 -8,-4s-8,0.5 -8,4v10.5zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM18,10L6,10L6,5h12v5z"/>
+</vector>




diff --git a/app/src/main/res/drawable/train_black.xml b/app/src/main/res/drawable/train_black.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ba7a9afcdaa5f94c0f8dd673781d7647b6055ea4
--- /dev/null
+++ b/app/src/main/res/drawable/train_black.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" 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>