Author: Adam Evyčędo <git@apiote.xyz>
use elizabeth dev responses to show inexact times and lines in change options
%!v(PANIC=String method: strings: negative Repeat count)
diff --git a/app/src/debug/java/xyz/apiote/bimba/czwek/api/responses/DevResponses.kt b/app/src/debug/java/xyz/apiote/bimba/czwek/api/responses/DevResponses.kt index e7e36dc7168480786df2c912ee01962d0bfb3826..bb77730d3df8a610a21d21b72dbb39116f45d245 100644 --- a/app/src/debug/java/xyz/apiote/bimba/czwek/api/responses/DevResponses.kt +++ b/app/src/debug/java/xyz/apiote/bimba/czwek/api/responses/DevResponses.kt @@ -5,11 +5,11 @@ package xyz.apiote.bimba.czwek.api.responses import xyz.apiote.bimba.czwek.api.AlertV1 -import xyz.apiote.bimba.czwek.api.DepartureV4 +import xyz.apiote.bimba.czwek.api.DepartureV5 import xyz.apiote.bimba.czwek.api.LineV3 -import xyz.apiote.bimba.czwek.api.LocatableV3 -import xyz.apiote.bimba.czwek.api.QueryableV4 -import xyz.apiote.bimba.czwek.api.StopV2 +import xyz.apiote.bimba.czwek.api.LocatableV4 +import xyz.apiote.bimba.czwek.api.QueryableV5 +import xyz.apiote.bimba.czwek.api.StopV3 import xyz.apiote.bimba.czwek.api.UnknownResourceVersionException import xyz.apiote.bimba.czwek.api.VehicleV3 import xyz.apiote.bimba.czwek.api.structs.FeedInfoV2 @@ -18,13 +18,13 @@ import java.io.InputStream data class DeparturesResponseDev( val alerts: List<AlertV1>, - val departures: List<DepartureV4>, - val stop: StopV2 + val departures: List<DepartureV5>, + val stop: StopV3 ) : DeparturesResponse { companion object { fun unmarshal(stream: InputStream): DeparturesResponseDev { val alerts = mutableListOf<AlertV1>() - val departures = mutableListOf<DepartureV4>() + val departures = mutableListOf<DepartureV5>() val reader = Reader(stream) val alertsNum = reader.readUInt().toULong() @@ -34,11 +34,11 @@ alerts.add(alert) } val departuresNum = reader.readUInt().toULong() for (i in 0UL until departuresNum) { - val departure = DepartureV4.unmarshal(stream) + val departure = DepartureV5.unmarshal(stream) departures.add(departure) } - return DeparturesResponseDev(alerts, departures, StopV2.unmarshal(stream)) + return DeparturesResponseDev(alerts, departures, StopV3.unmarshal(stream)) } } } @@ -69,16 +69,16 @@ } } } -data class LocatablesResponseDev(val locatables: List<LocatableV3>) : LocatablesResponse { +data class LocatablesResponseDev(val locatables: List<LocatableV4>) : LocatablesResponse { companion object { fun unmarshal(stream: InputStream): LocatablesResponseDev { - val locatables = mutableListOf<LocatableV3>() + val locatables = mutableListOf<LocatableV4>() val reader = Reader(stream) val n = reader.readUInt().toULong() for (i in 0UL until n) { when (val r = reader.readUInt().toULong()) { 0UL -> { - locatables.add(StopV2.unmarshal(stream)) + locatables.add(StopV3.unmarshal(stream)) } 1UL -> { @@ -96,16 +96,16 @@ } } -data class QueryablesResponseDev(val queryables: List<QueryableV4>) : QueryablesResponse { +data class QueryablesResponseDev(val queryables: List<QueryableV5>) : QueryablesResponse { companion object { fun unmarshal(stream: InputStream): QueryablesResponseDev { - val queryables = mutableListOf<QueryableV4>() + val queryables = mutableListOf<QueryableV5>() val reader = Reader(stream) val n = reader.readUInt().toULong() for (i in 0UL until n) { when (val r = reader.readUInt().toULong()) { 0UL -> { - queryables.add(StopV2.unmarshal(stream)) + queryables.add(StopV3.unmarshal(stream)) } 1UL -> { diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt index 76953700a4a76e06a41716bcdcc43d07e50e1008..0d66dc74963b07142e773eb533bda2804a66e12a 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt @@ -82,7 +82,11 @@ "queryables", null, params, context, - arrayOf(1u, 2u, 3u, 4u), + if (server.apiPath == "https://bimba.apiote.xyz/next") { + arrayOf(1u, 2u, 3u, 4u, 0u) + } else { + arrayOf(1u, 2u, 3u, 4u) + }, null ) } 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 4bfc2f5c505cd365ec5a973bc01a4558856f35c9..ae3a82af89e9bd12e3796f093a0ad2d14362c6a0 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 @@ -8,6 +8,8 @@ interface QueryableV1 interface QueryableV2 interface QueryableV3 interface QueryableV4 +interface QueryableV5 interface LocatableV1 interface LocatableV2 -interface LocatableV3 \ No newline at end of file +interface LocatableV3 +interface LocatableV4 \ No newline at end of file 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 9e604c62e01918732d5d03565aa5492cb5989dd5..62d9c8a13101ed601d9234c19ba9b2b8551b6f9b 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 @@ -198,7 +198,8 @@ } } } -data class ColourV1(val R: UByte, val G: UByte, val B: UByte) { +@Parcelize +data class ColourV1(val R: UByte, val G: UByte, val B: UByte): Parcelable { companion object { fun unmarshal(stream: InputStream): ColourV1 { val reader = Reader(stream) @@ -309,7 +310,7 @@ val Line: LineStubV3, val Headsign: String, val CongestionLevel: CongestionLevelV1, val OccupancyStatus: OccupancyStatusV1 -) : LocatableV3 { +) : LocatableV3, LocatableV4 { companion object { fun unmarshal(stream: InputStream): VehicleV3 { val reader = Reader(stream) @@ -327,9 +328,10 @@ } } } +@Parcelize data class LineStubV1( val name: String, val kind: LineTypeV1, val colour: ColourV1 -) { +):Parcelable { companion object { fun unmarshal(stream: InputStream): LineStubV1 { val reader = Reader(stream) @@ -470,6 +472,76 @@ } } } +data class DepartureV5( + val ID: String, + val time: Time, + val status: VehicleStatusV1, + val isRealtime: Boolean, + val vehicle: VehicleV3, + val boarding: UByte, + val alerts: List<AlertV1>, + val exact: Boolean, + val terminusArrival: Boolean +) { + + companion object { + fun unmarshal(stream: InputStream): DepartureV5 { + val reader = Reader(stream) + val id = reader.readString() + val time = Time.unmarshal(stream) + val status = VehicleStatusV1.of(reader.readUInt().toULong().toUInt()) + val isRealtime = reader.readBoolean() + val vehicle = VehicleV3.unmarshal(stream) + val boarding = reader.readU8() + val alertsNum = reader.readUInt().toULong() + val alerts = mutableListOf<AlertV1>() + for (i in 0UL until alertsNum) { + alerts.add(AlertV1.unmarshal(stream)) + } + val exact = reader.readBoolean() + val terminusArrival = reader.readBoolean() + return DepartureV5(id, time, status, isRealtime, vehicle, boarding, alerts, exact, terminusArrival) + } + } +} + +@Parcelize +data class StopV3( + val code: String, + val name: String, + val nodeName: String, + val zone: String, + val feedID: String, + val position: PositionV1, + val changeOptions: List<ChangeOptionV2> +) : Parcelable, LocatableV4, QueryableV5 { + companion object { + fun unmarshal(stream: InputStream): StopV3 { + val reader = Reader(stream) + val code = reader.readString() + val name = reader.readString() + val nodeName = reader.readString() + val zone = reader.readString() + val feedID = reader.readString() + val position = PositionV1.unmarshal(stream) + val chOptionsNum = reader.readUInt().toULong() + val changeOptions = mutableListOf<ChangeOptionV2>() + for (i in 0UL until chOptionsNum) { + changeOptions.add(ChangeOptionV2.unmarshal(stream)) + } + return StopV3( + name = name, + nodeName = nodeName, + code = code, + zone = zone, + position = position, + feedID = feedID, + changeOptions = changeOptions + ) + } + } +} + @Parcelize data class StopV2( val code: String, @@ -632,7 +704,7 @@ val type: LineTypeV3, val feedID: String, val headsigns: List<List<String>>, val graphs: List<LineGraph>, -) : QueryableV4 { +) : QueryableV4, QueryableV5 { override fun toString(): String { return "$name ($type) [$colour]\n${headsigns.map { "-> ${it.joinToString()}" }}" } @@ -722,6 +794,21 @@ 9u -> valueOf("FUNICULAR") 10u -> valueOf("MONORAIL") else -> throw UnknownResourceVersionException("LineType/$type", 3u) } + } + } +} + +@Parcelize +data class ChangeOptionV2(val line: LineStubV1, val headsigns: List<String>) : Parcelable { + companion object { + fun unmarshal(stream: InputStream): ChangeOptionV2 { + val reader = Reader(stream) + val line = LineStubV1.unmarshal(stream) + val headsignsNum = reader.readUInt().toULong().toInt() + val headsigns = (0 until headsignsNum).map { + reader.readString() + } + return ChangeOptionV2(line = line, headsigns = headsigns) } } } diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Departures.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Departures.kt index 0d053162b88f3d4f2a65975d1d2cff92e2b979a4..4e22e00b1b8365b32fc365f86c904dd74366651c 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Departures.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Departures.kt @@ -19,7 +19,7 @@ companion object { fun unmarshal(stream: InputStream): DeparturesResponse { val reader = Reader(stream) return when (val v = reader.readUInt().toULong()) { - // 0UL -> DeparturesResponseDev.unmarshal(stream) + 0UL -> DeparturesResponseDev.unmarshal(stream) 1UL -> DeparturesResponseV1.unmarshal(stream) 2UL -> DeparturesResponseV2.unmarshal(stream) 3UL -> DeparturesResponseV3.unmarshal(stream) diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Locatables.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Locatables.kt index a176bd2dff780abb44aa27b89af2679233679fe7..2188e29c3297dc5614ce30f40b4bb359a67781f0 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Locatables.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Locatables.kt @@ -21,7 +21,7 @@ companion object { fun unmarshal(stream: InputStream): LocatablesResponse { val reader = Reader(stream) return when (val v = reader.readUInt().toULong()) { - // 0UL -> LocatablesResponseDev.unmarshal(stream) + 0UL -> LocatablesResponseDev.unmarshal(stream) 1UL -> LocatablesResponseV1.unmarshal(stream) 2UL -> LocatablesResponseV2.unmarshal(stream) 3UL -> LocatablesResponseV3.unmarshal(stream) @@ -34,7 +34,7 @@ data class LocatablesResponseV3(val locatables: List<LocatableV3>) : LocatablesResponse { companion object { - fun unmarshal(stream: InputStream): LocatablesResponseDev { + fun unmarshal(stream: InputStream): LocatablesResponseV3 { val locatables = mutableListOf<LocatableV3>() val reader = Reader(stream) val n = reader.readUInt().toULong() @@ -53,7 +53,7 @@ throw UnknownResourceVersionException("Locatable/$r", 0u) } } } - return LocatablesResponseDev(locatables) + return LocatablesResponseV3(locatables) } } } diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Queryables.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Queryables.kt index 8e7cc8f8c7a63204b4c2d69604ae33f2fe4ac768..216ab34e80475121dde939626338c14e59e382cb 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Queryables.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Queryables.kt @@ -22,7 +22,7 @@ companion object { fun unmarshal(stream: InputStream): QueryablesResponse { val reader = Reader(stream) return when (val v = reader.readUInt().toULong()) { - // 0UL -> QueryablesResponseDev.unmarshal(stream) + 0UL -> QueryablesResponseDev.unmarshal(stream) 1UL -> QueryablesResponseV1.unmarshal(stream) 2UL -> QueryablesResponseV2.unmarshal(stream) 3UL -> QueryablesResponseV3.unmarshal(stream) diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt index 054385b6785da668fc461fee763808be6f371166..6761cf6abca84e34c17a37b63e36ca2fe1992b9e 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt @@ -187,7 +187,7 @@ Toast.makeText(context, ctx.getString(R.string.no_map_app), Toast.LENGTH_SHORT).show() } } - stop.changeOptions(ctx).let { changeOptions -> + stop.changeOptions(ctx, Stop.LineDecoration.NONE).let { changeOptions -> content.findViewById<TextView>(R.id.change_options).apply { text = changeOptions.first contentDescription = changeOptions.second diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt b/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt index bd20eaf7e474954a96ea993491dddebf413e1fb9..a59744516071cdef554282c14ffd0a342a9b3fff 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt @@ -51,6 +51,7 @@ val lineIcon: ImageView = itemView.findViewById(R.id.line_icon) val departureTime: TextView = itemView.findViewById(R.id.departure_time) val lineName: TextView = itemView.findViewById(R.id.departure_line) val headsign: TextView = itemView.findViewById(R.id.departure_headsign) + val timeStatus: ImageView = itemView.findViewById(R.id.time_status) companion object { fun bind( @@ -73,8 +74,31 @@ context?.getString( R.string.departure_headsign_content_description, departure.vehicle.Headsign ) + when { + departure.isRealtime -> { + holder?.timeStatus?.setImageResource(R.drawable.radar) + holder?.timeStatus?.contentDescription = context?.getString(R.string.realtime_content_description) + holder?.timeStatus?.let { TooltipCompat.setTooltipText(it, context?.getString(R.string.realtime_content_description)) } + } + departure.exact -> { + holder?.timeStatus?.setImageResource(R.drawable.calendar) + holder?.timeStatus?.contentDescription = context?.getString(R.string.exact_content_description) + holder?.timeStatus?.let { TooltipCompat.setTooltipText(it, context?.getString(R.string.exact_content_description)) } + } + else -> { + holder?.timeStatus?.setImageResource(R.drawable.inexact) + holder?.timeStatus?.contentDescription = context?.getString(R.string.inexact_content_description) + holder?.timeStatus?.let { TooltipCompat.setTooltipText(it, context?.getString(R.string.inexact_content_description)) } + } + } holder?.departureTime?.text = departure.statusText(context, showAsTime) + if (departure.terminusArrival) { + holder?.departureTime?.alpha = .5f + holder?.lineIcon?.alpha = .5f + holder?.lineName?.alpha = .5f + holder?.headsign?.alpha = .5f + } } } } @@ -138,7 +162,9 @@ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { val oldDeparture = oldDepartures[oldItemPosition] val newDeparture = newDepartures[newItemPosition] return if (oldDeparture.departure != null && newDeparture.departure != null) { - oldDeparture.departure.vehicle.Line == newDeparture.departure.vehicle.Line && + oldDeparture.departure.terminusArrival == newDeparture.departure.terminusArrival && + oldDeparture.departure.exact == newDeparture.departure.exact && + oldDeparture.departure.vehicle.Line == newDeparture.departure.vehicle.Line && oldDeparture.departure.vehicle.Headsign == newDeparture.departure.vehicle.Headsign && oldDeparture.departure.statusText( context, diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt index 1164836fb36f512ff578e26a75e9c1ac04013cac..7cb5e9c07c7093ca8c6fada65b4d80e54bff7e30 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt @@ -447,7 +447,9 @@ stop: Stop?, leaveAlert: Boolean = false ) { setupSnackbar() - binding.departuresRecycler.scrollToPosition(0) + if (adapter.itemCount == 0) { + binding.departuresRecycler.scrollToPosition(0) + } binding.departuresProgress.visibility = View.GONE // TODO [elizabeth] max, progress from header Cache-Control max-age binding.departuresUpdatesProgress.apply { diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/ChangeOption.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/ChangeOption.kt index b41f089279301f16959982baf3d256b52c5512ad..110e85d8f3bea00613dcb3c89ed024dac1a4f4f4 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/ChangeOption.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/ChangeOption.kt @@ -5,7 +5,9 @@ package xyz.apiote.bimba.czwek.repo import xyz.apiote.bimba.czwek.api.ChangeOptionV1 +import xyz.apiote.bimba.czwek.api.ChangeOptionV2 -data class ChangeOption(val line: String, val headsign: String) { - constructor(c: ChangeOptionV1) : this(c.line, c.headsign) +data class ChangeOption(val line: LineStub, val headsigns: List<String>) { + constructor(c: ChangeOptionV1) : this(LineStub(c.line, LineType.UNKNOWN, Colour(0u,0u,0u)), listOf(c.headsign)) + constructor(c: ChangeOptionV2) : this(LineStub(c.line), c.headsigns) } \ No newline at end of file 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 b3459fda1568096322caab7e16e7dace0d9b87a6..66ac62094ec48793ce330634aa369da2d1b18c68 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 @@ -14,6 +14,7 @@ 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.DepartureV4 +import xyz.apiote.bimba.czwek.api.DepartureV5 import xyz.apiote.bimba.czwek.api.Time import xyz.apiote.bimba.czwek.api.UnknownResourceVersionException import xyz.apiote.bimba.czwek.units.Second @@ -115,7 +116,9 @@ val status: ULong, val isRealtime: Boolean, val vehicle: Vehicle, val boarding: UByte, - val alerts: List<Alert> + val alerts: List<Alert>, + val exact: Boolean, + val terminusArrival: Boolean ) { constructor(d: DepartureV1) : this( @@ -125,7 +128,9 @@ d.status, d.isRealtime, Vehicle(d.vehicle), d.boarding, - emptyList() + emptyList(), + true, + false ) constructor(d: DepartureV2) : this( @@ -135,7 +140,9 @@ d.status, d.isRealtime, Vehicle(d.vehicle), d.boarding, - emptyList() + emptyList(), + true, + false ) constructor(d: DepartureV3) : this( @@ -145,7 +152,9 @@ d.status.ordinal.toULong(), // TODO VehicleStatus d.isRealtime, Vehicle(d.vehicle), d.boarding, - emptyList() + emptyList(), + true, + false ) constructor(d: DepartureV4) : this( @@ -155,7 +164,21 @@ d.status.ordinal.toULong(), // TODO VehicleStatus d.isRealtime, Vehicle(d.vehicle), d.boarding, - d.alerts.map { Alert(it) } + d.alerts.map { Alert(it) }, + true, + false + ) + + constructor(d: DepartureV5) : this( + d.ID, + d.time, + d.status.ordinal.toULong(), // TODO VehicleStatus + d.isRealtime, + Vehicle(d.vehicle), + d.boarding, + d.alerts.map { Alert(it) }, + d.exact, + d.terminusArrival ) fun statusText(context: Context?, showAsTime: Boolean, at: ZonedDateTime? = null): String { @@ -195,12 +218,13 @@ } } fun timeString(context: Context): String { - return if (isRealtime) { - context.getString( + return when { + isRealtime -> context.getString( R.string.at_time_realtime, time.Hour.toInt(), time.Minute.toInt(), time.Second.toInt() ) - } else { - context.getString(R.string.at_time, time.Hour.toInt(), time.Minute.toInt()) + + exact -> context.getString(R.string.at_time, time.Hour.toInt(), time.Minute.toInt()) + else -> context.getString(R.string.about_time, time.Hour.toInt(), time.Minute.toInt()) } } diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/FeedInfo.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/FeedInfo.kt index 3d645e655861a1f67f3694aa12da1ab90eb1d675..d7d1924cfa5e28c9a41b7433bde9aa7608279cdf 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/FeedInfo.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/FeedInfo.kt @@ -18,7 +18,7 @@ import java.util.Locale class FeedInfoPrev { companion object { - fun unmarshal(stream: InputStream): FeedInfo { + fun unmarshal(@Suppress("UNUSED_PARAMETER") stream: InputStream): FeedInfo { return FeedInfo(FeedInfoPrev()) } } @@ -100,7 +100,7 @@ null, cached ) - constructor(f: FeedInfoPrev) : this( + constructor(@Suppress("UNUSED_PARAMETER") f: FeedInfoPrev) : this( "", "", "", 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 d5ecc9bbbba7111c55e31d0015ce15f696e17274..db2525fa84c91a88fb53b7d6c1b40de93540f8d7 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 @@ -67,9 +67,9 @@ 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.CABLE_TRAM -> R.drawable.cablecar_black + LineType.CABLE_CAR -> R.drawable.cabletram_black + LineType.FUNICULAR -> R.drawable.funicular_black LineType.MONORAIL -> R.drawable.monorail_black LineType.UNKNOWN -> R.drawable.vehicle_black } 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 1c3f36595fe1c6bc646a137d9475294d59f0f9d1..1ba24e3cbe16562fe30e5fb186d1087c948659c4 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 @@ -14,6 +14,7 @@ import xyz.apiote.bimba.czwek.api.PositionV1 import xyz.apiote.bimba.czwek.api.Server import xyz.apiote.bimba.czwek.api.StopV1 import xyz.apiote.bimba.czwek.api.StopV2 +import xyz.apiote.bimba.czwek.api.StopV3 import xyz.apiote.bimba.czwek.api.UnknownResourceException import xyz.apiote.bimba.czwek.api.VehicleV1 import xyz.apiote.bimba.czwek.api.VehicleV2 @@ -171,7 +172,7 @@ return when (val response = withContext(Dispatchers.IO) { LocatablesResponse.unmarshal(result.stream!!) }) { is LocatablesResponseDev -> response.locatables.map { when (it) { - is StopV2 -> Stop(it) + is StopV3 -> Stop(it) is VehicleV3 -> Vehicle(it) else -> throw UnknownResourceException("locatables", it::class) } @@ -273,7 +274,7 @@ return when (val response = withContext(Dispatchers.IO) { QueryablesResponse.unmarshal(result.stream!!) }) { is QueryablesResponseDev -> response.queryables.map { when (it) { - is StopV2 -> Stop(it) + is StopV3 -> Stop(it) is LineV3 -> Line(it) else -> throw UnknownResourceException("queryablesV4", it::class) } diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt index 0c6909006f92fe6a5bc7add619c14d4b7cc7a0a4..662b6d26c696a2096f634ecfab49e7af6d7aacdb 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt @@ -5,10 +5,20 @@ package xyz.apiote.bimba.czwek.repo import android.content.Context +import android.graphics.Typeface import android.graphics.drawable.Drawable +import android.text.Annotation +import android.text.Spannable +import android.text.SpannableStringBuilder +import android.text.Spanned +import android.text.SpannedString +import android.text.style.BackgroundColorSpan +import android.text.style.StyleSpan +import androidx.preference.PreferenceManager import xyz.apiote.bimba.czwek.R import xyz.apiote.bimba.czwek.api.StopV1 import xyz.apiote.bimba.czwek.api.StopV2 +import xyz.apiote.bimba.czwek.api.StopV3 data class Stop( val code: String, @@ -46,22 +56,118 @@ s.feedID, Position(s.position), s.changeOptions.map { ChangeOption(it) }) - fun changeOptions(context: Context): Pair<String, String> = Pair(changeOptions.groupBy { it.line } - .map { Pair(it.key, it.value.joinToString { co -> co.headsign }) }.joinToString { - context.getString( - R.string.vehicle_headsign, it.first, it.second - ) - }, - changeOptions.groupBy { it.line } - .map { Pair(it.key, it.value.joinToString { co -> co.headsign }) }.joinToString { - context.getString( - R.string.vehicle_headsign_content_description, it.first, it.second + constructor(s: StopV3) : this( + s.code, + s.name, + s.nodeName, + s.zone, + s.feedID, + Position(s.position), + s.changeOptions.map { ChangeOption(it) }) + + fun changeOptions(context: Context, decoration: LineDecoration): Pair<Spannable, String> { + return Pair(changeOptions.groupBy { it.line } + .map { + Pair( + it.key, + it.value.flatMap { co -> co.headsigns }.sortedBy { headsign -> headsign }.joinToString() + ) + }.fold(SpannableStringBuilder("")) { acc, p -> + if (acc.toString() != "") { + acc.append("; ") + } + var str = SpannableStringBuilder( + context.getText( + R.string.vehicle_headsign + ) as SpannedString ) - }) + str = applyAnnotations(str, decoration, p.first, p.first.name, p.second) + str = applyAnnotations(str, decoration, p.first) + acc.append(str) + acc + }, + changeOptions.groupBy { it.line } + .map { + Pair( + it.key, + it.value.flatMap { co -> co.headsigns }.sortedBy { headsign -> headsign }.joinToString() + ) + }.joinToString { + context.getString( + R.string.vehicle_headsign_content_description, it.first, it.second + ) + }) + } + + private fun applyAnnotations( + s: SpannableStringBuilder, + decoration: LineDecoration, + line: LineStub, + vararg args: Any + ): SpannableStringBuilder { + val str = SpannableStringBuilder(s) + val annotations = str.getSpans(0, str.length, Annotation::class.java) + annotations.forEach { + when (it.key) { + "arg" -> { + if (args.isEmpty()) { + return@forEach + } + val argIndex = Integer.parseInt(it.value) + str.replace(str.getSpanStart(it), str.getSpanEnd(it), args[argIndex] as String) + } + + "decoration" -> { + if (args.isNotEmpty()) { + return@forEach + } + val background = BackgroundColorSpan(line.colour.toInt()) + val foreground = line.textColour(line.colour) + val ital = StyleSpan(Typeface.ITALIC) + when (decoration) { + LineDecoration.ITALICS -> str.setSpan( + ital, + str.getSpanStart(it), + str.getSpanEnd(it), + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ) + + LineDecoration.COLOUR -> { + str.setSpan(background, str.getSpanStart(it), str.getSpanEnd(it), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + str.setSpan(foreground, str.getSpanStart(it), str.getSpanEnd(it), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + } + + LineDecoration.NONE -> {} + } + } + } + } + return str + } + + fun changeOptionsString(): String = changeOptions.groupBy { it.line } + .map { + Pair( + it.key, + it.value.flatMap { co -> co.headsigns }.sortedBy { headsign -> headsign }.joinToString() + ) + }.joinToString("; ") override fun toString(): String { - var result = "$name ($code) [$zone] $position\n" - for (chOpt in changeOptions) result += "${chOpt.line} → ${chOpt.headsign}\n" - return result + return "$name ($code) [$zone] $position\n${changeOptionsString()}" + } + + enum class LineDecoration { + NONE, ITALICS, COLOUR; + companion object { + fun fromPreferences(context: Context) = + when (PreferenceManager.getDefaultSharedPreferences(context) + .getString("line_decoration", "italics")) { + "italics" -> Stop.LineDecoration.ITALICS + "colour" -> Stop.LineDecoration.COLOUR + "none" -> Stop.LineDecoration.NONE + else -> Stop.LineDecoration.ITALICS + } + } } } \ No newline at end of file diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/search/Results.kt b/app/src/main/java/xyz/apiote/bimba/czwek/search/Results.kt index 7ce6dc062432c68e176a752e609cc2b966dbef52..a13611c7ee852e3421c01a0bdc651128d0ef2d6f 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/search/Results.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/search/Results.kt @@ -144,7 +144,7 @@ holder?.feedName?.visibility = View.VISIBLE holder?.feedName?.text = feeds?.get(stop.feedID)?.name ?: "" } context?.let { - stop.changeOptions(it).let { changeOptions -> + stop.changeOptions(it, Stop.LineDecoration.fromPreferences(context)).let { changeOptions -> holder?.description?.apply { text = changeOptions.first contentDescription = changeOptions.second @@ -257,10 +257,8 @@ } is Stop -> { assert(newQueryable is Stop) - val oldChangeOptions = - oldQueryable.changeOptions.joinToString { "${it.line}->${it.headsign}" } - val newChangeOptions = - (newQueryable as Stop).changeOptions.joinToString { "${it.line}->${it.headsign}" } + val oldChangeOptions = oldQueryable.changeOptionsString() + val newChangeOptions = (newQueryable as Stop).changeOptionsString() oldQueryable.name == newQueryable.name && oldChangeOptions == newChangeOptions && oldPosition?.latitude == newPosition?.latitude && oldPosition?.longitude == newPosition?.longitude && diff --git a/app/src/main/res/drawable/cablecar_black.xml b/app/src/main/res/drawable/cablecar_black.xml new file mode 100644 index 0000000000000000000000000000000000000000..4f2979fcb7103f73915f871cf103dcba9e06c3b9 --- /dev/null +++ b/app/src/main/res/drawable/cablecar_black.xml @@ -0,0 +1,17 @@ +<!-- +SPDX-FileCopyrightText: Austin Andrews + +SPDX-License-Identifier: Apache-2.0 + +source: https://pictogrammers.com/library/mdi/icon/gondola/ +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#000000" + android:pathData="M18,10H13V7.59L22.12,6.07L21.88,4.59L16.41,5.5C16.46,5.35 16.5,5.18 16.5,5A1.5,1.5 0 0,0 15,3.5A1.5,1.5 0 0,0 13.5,5C13.5,5.35 13.63,5.68 13.84,5.93L13,6.07V5H11V6.41L10.41,6.5C10.46,6.35 10.5,6.18 10.5,6A1.5,1.5 0 0,0 9,4.5A1.5,1.5 0 0,0 7.5,6C7.5,6.36 7.63,6.68 7.83,6.93L1.88,7.93L2.12,9.41L11,7.93V10H6C4.89,10 4,10.9 4,12V18A2,2 0 0,0 6,20H18A2,2 0 0,0 20,18V12A2,2 0 0,0 18,10M6,12H8.25V16H6V12M9.75,16V12H14.25V16H9.75M18,16H15.75V12H18V16Z" /> +</vector> \ No newline at end of file diff --git a/app/src/main/res/drawable/cabletram_black.xml b/app/src/main/res/drawable/cabletram_black.xml new file mode 100644 index 0000000000000000000000000000000000000000..3947ee16f0d93ca3e4c67b9e861a0309e6ec255b --- /dev/null +++ b/app/src/main/res/drawable/cabletram_black.xml @@ -0,0 +1,44 @@ +<!-- +SPDX-FileCopyrightText: Jamison Wieser + +SPDX-License-Identifier: CC0-1.0 + +source: https://thenounproject.com/icon/cable-car-4173/ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="1600" + android:viewportHeight="1600"> + <group + android:translateX="200" + android:translateY="200"> + <path + android:fillColor="#000000" + android:pathData="m166.5,228v48.2h48.2v413.8h770.7v-413.9h48.1v-48.2c-289,-96.3 -578,-96.3 -867,0zM455.5,641.8h-192.6v-316.5c64.2,-38.5 128.4,-38.5 192.6,0 -0,38.5 -0,316.5 -0,316.5zM696.3,641.8h-192.6v-316.5c64.2,-38.5 128.4,-38.5 192.6,0 -0,38.5 -0,316.5 -0,316.5zM937.1,641.8h-192.6v-316.5c64.2,-38.5 128.4,-38.5 192.6,0v316.5z" /> + + <path + android:fillColor="#000000" + android:pathData="m214.7,714.6v262.6h770.7l-0,-262.6zM600,894.8c-26.6,0 -48.2,-21.6 -48.2,-48.2 0,-26.6 21.6,-48.1 48.2,-48.1 26.6,0 48.2,21.5 48.2,48.1 0,26.6 -21.6,48.2 -48.2,48.2z" /> + + <path + android:fillColor="#000000" + android:pathData="m985.3,1055.5v-48.2h-770.7v48.2h-96.3v48.1h125.2c10.6,0 25.4,-6.1 32.9,-13.6l21,-21c6.2,-6.2 17.3,-11.4 27,-13 16.7,2.7 19.2,15 4.6,29.6l-84.2,84.2c-16.6,16.6 -11,30.2 12.4,30.2h685.4c23.4,0 29.1,-13.6 12.5,-30.2l-84.2,-84.2c-14.5,-14.5 -12,-26.8 4.7,-29.6 9.6,1.7 20.8,6.8 27,13l20.9,21c7.5,7.5 22.3,13.6 32.9,13.6h125.2v-48.1h-96.3z" /> + + <path + android:fillColor="#000000" + android:pathData="m359.2,146.4c192.6,-24.1 289,-24.1 481.6,0v-24.1h48.2v-24.1c-192.7,-48.2 -385.3,-48.2 -578,0v24.1h48.2v24.1z" /> + + <path + android:fillColor="#000000" + android:pathData="m648.2,46c-1.2,-25.6 -22.3,-46 -48.2,-46 -25.9,0 -47,20.4 -48.2,46 32.1,-2.8 64.3,-2.8 96.4,0z" /> + + <path + android:fillColor="#000000" + android:pathData="m189.4,446c0,-10.8 -8.8,-19.6 -19.7,-19.6s-19.6,8.8 -19.6,19.6v458.3c0,10.8 8.7,19.6 19.6,19.6 10.9,0 19.7,-8.8 19.7,-19.6z" /> + + <path + android:fillColor="#000000" + android:pathData="m1049.9,446c0,-10.8 -8.8,-19.6 -19.6,-19.6 -10.9,0 -19.7,8.8 -19.7,19.6v458.3c0,10.8 8.8,19.6 19.7,19.6 10.8,0 19.6,-8.8 19.6,-19.6z" /> + </group> +</vector> diff --git a/app/src/main/res/drawable/funicular_black.xml b/app/src/main/res/drawable/funicular_black.xml new file mode 100644 index 0000000000000000000000000000000000000000..3472477cc7d19902ba293b28b182f8ab6a52d069 --- /dev/null +++ b/app/src/main/res/drawable/funicular_black.xml @@ -0,0 +1,25 @@ +<!-- +SPDX-FileCopyrightText: Daniel Calliess + +SPDX-License-Identifier: CC0-1.0 + +source: https://thenounproject.com/icon/funicular-635171/ +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="1600" + android:viewportHeight="1600"> + <group + android:translateX="200" + android:translateY="200"> + <path + android:fillColor="#000000" + android:pathData="m60,1086 l1080,-624.6v54l-1080,624.6z" /> + + <path + android:fillColor="#000000" + android:pathData="m81.6,663c-12,6.9 -21.6,22.1 -21.6,34.1v313.3c0,12 9.6,16 21.6,9.1l1036.8,-599.6c12,-6.9 21.6,-22.1 21.6,-34.1v-313.3c0,-12 -9.6,-16 -21.6,-9.1zM135.6,696.6 L387.7,550.8c6,-3.5 10.8,-1.4 10.8,4.6v172.9c0,6 -4.8,13.6 -10.8,17.1l-252.1,145.8c-6,3.5 -10.8,1.4 -10.8,-4.6v-172.9c0,-6 4.8,-13.6 10.8,-17.1zM474.1,500.8 L725.9,355.2c6,-3.5 10.8,-1.4 10.8,4.6v172.9c0,6 -4.8,13.6 -10.8,17.1l-251.8,145.6c-6,3.5 -10.8,1.4 -10.8,-4.6v-172.9c0,-6 4.8,-13.6 10.8,-17.1zM812.3,305.2 L1064.4,159.4c6,-3.5 10.8,-1.4 10.8,4.6v172.9c0,6 -4.8,13.6 -10.8,17.1l-252.1,145.8c-6,3.5 -10.8,1.4 -10.8,-4.6v-172.9c0,-6 4.8,-13.6 10.8,-17.1z" /> + </group> +</vector> diff --git a/app/src/main/res/drawable/inexact.xml b/app/src/main/res/drawable/inexact.xml new file mode 100644 index 0000000000000000000000000000000000000000..d1ba0403097cbc7a980bc9d5ddfd921596069d04 --- /dev/null +++ b/app/src/main/res/drawable/inexact.xml @@ -0,0 +1,17 @@ +<!-- +SPDX-FileCopyrightText: Michael Irigoyen + +SPDX-License-Identifier: Apache-2.0 + +source: https://pictogrammers.com/library/mdi/icon/tilde/ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorOnSurface" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#000000" + android:pathData="M2,15C2,15 2,9 8,9C12,9 12.5,12.5 15.5,12.5C19.5,12.5 19.5,9 19.5,9H22C22,9 22,15 16,15C12,15 10.5,11.5 8.5,11.5C4.5,11.5 4.5,15 4.5,15H2" /> +</vector> \ No newline at end of file diff --git a/app/src/main/res/drawable/info.xml b/app/src/main/res/drawable/info.xml new file mode 100644 index 0000000000000000000000000000000000000000..2131db7742b29fd42abe5a1bf96f90e2233eadae --- /dev/null +++ b/app/src/main/res/drawable/info.xml @@ -0,0 +1,18 @@ +<!-- +SPDX-FileCopyrightText: Google + +SPDX-License-Identifier: Apache-2.0 +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorOnSurface" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="@android:color/white" + android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z" /> + +</vector> diff --git a/app/src/main/res/drawable/settings.xml b/app/src/main/res/drawable/settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..e363b3e6e6567aa5db2c040f4432ddd803247b10 --- /dev/null +++ b/app/src/main/res/drawable/settings.xml @@ -0,0 +1,18 @@ +<!-- +SPDX-FileCopyrightText: Google + +SPDX-License-Identifier: Apache-2.0 +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorOnSurface" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="@android:color/white" + android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z" /> + +</vector> diff --git a/app/src/main/res/drawable/speed.xml b/app/src/main/res/drawable/speed.xml index 67e8c0ca8f57a67bc7480bc1d8ba887928814491..139f3480d252286fa5ef0522b2d89b0f5300426c 100644 --- a/app/src/main/res/drawable/speed.xml +++ b/app/src/main/res/drawable/speed.xml @@ -4,8 +4,13 @@ SPDX-License-Identifier: Apache-2.0 --> -<vector android:height="24dp" android:tint="?attr/colorOnSurface" - 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.38,8.57l-1.23,1.85a8,8 0,0 1,-0.22 7.58L5.07,18A8,8 0,0 1,15.58 6.85l1.85,-1.23A10,10 0,0 0,3.35 19a2,2 0,0 0,1.72 1h13.85a2,2 0,0 0,1.74 -1,10 10,0 0,0 -0.27,-10.44zM10.59,15.41a2,2 0,0 0,2.83 0l5.66,-8.49 -8.49,5.66a2,2 0,0 0,0 2.83z"/> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorOnSurface" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="M20.38,8.57l-1.23,1.85a8,8 0,0 1,-0.22 7.58L5.07,18A8,8 0,0 1,15.58 6.85l1.85,-1.23A10,10 0,0 0,3.35 19a2,2 0,0 0,1.72 1h13.85a2,2 0,0 0,1.74 -1,10 10,0 0,0 -0.27,-10.44zM10.59,15.41a2,2 0,0 0,2.83 0l5.66,-8.49 -8.49,5.66a2,2 0,0 0,0 2.83z" /> </vector> diff --git a/app/src/main/res/drawable/vehicle.xml b/app/src/main/res/drawable/vehicle.xml new file mode 100644 index 0000000000000000000000000000000000000000..6f99d217d5e9cf41d2ea910980fd338244a1b1f0 --- /dev/null +++ b/app/src/main/res/drawable/vehicle.xml @@ -0,0 +1,11 @@ +<!-- +SPDX-FileCopyrightText: Google + +SPDX-License-Identifier: Apache-2.0 +--> + +<vector android:height="24dp" android:tint="?attr/colorOnSurface" + 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,4L5,4C3.34,4 2,5.34 2,7v8c0,1.66 1.34,3 3,3l-1,1v1h1l2,-2.03L9,18v-5L4,13L4,5.98L13,6v2h2L15,7c0,-1.66 -1.34,-3 -3,-3zM5,14c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM20.57,9.66c-0.14,-0.4 -0.52,-0.66 -0.97,-0.66h-7.19c-0.46,0 -0.83,0.26 -0.98,0.66L10,13.77l0.01,5.51c0,0.38 0.31,0.72 0.69,0.72h0.62c0.38,0 0.68,-0.38 0.68,-0.76L12,18h8v1.24c0,0.38 0.31,0.76 0.69,0.76h0.61c0.38,0 0.69,-0.34 0.69,-0.72l0.01,-1.37v-4.14l-1.43,-4.11zM12.41,10h7.19l1.03,3h-9.25l1.03,-3zM12,16c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM20,16c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1z"/> +</vector> diff --git a/app/src/main/res/layout/departure.xml b/app/src/main/res/layout/departure.xml index 834cbe0773dbb70fe4aa6a9c8f26ac4d5b114224..b2514262349aef0d448fed775a6116b4042ece6d 100644 --- a/app/src/main/res/layout/departure.xml +++ b/app/src/main/res/layout/departure.xml @@ -37,14 +37,16 @@ tool:text="1hr" /> <com.google.android.material.textview.MaterialTextView android:id="@+id/departure_line" - android:layout_width="wrap_content" + android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" + android:layout_marginEnd="8dp" android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" app:layout_constraintStart_toEndOf="@+id/line_icon" app:layout_constraintTop_toTopOf="parent" - tool:text="Metropolitan" /> + app:layout_constraintEnd_toStartOf="@id/departure_time" + tool:text="Circle" /> <com.google.android.material.textview.MaterialTextView android:id="@+id/departure_headsign" @@ -55,5 +57,13 @@ app:layout_constraintStart_toStartOf="@+id/departure_line" app:layout_constraintTop_toBottomOf="@+id/departure_line" tool:text="» Tower Hill" /> - + <ImageView + android:id="@+id/time_status" + android:layout_width="12dp" + android:layout_height="12dp" + android:layout_marginEnd="8dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/departure_time" + tool:ignore="ContentDescription" + tool:srcCompat="@drawable/inexact" /> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/menu/drawer.xml b/app/src/main/res/menu/drawer.xml index 1d876c0cf374716191449dcfaf664152687c4623..5a5194c75d78419d3249ea66b2dc7a1e1354d202 100644 --- a/app/src/main/res/menu/drawer.xml +++ b/app/src/main/res/menu/drawer.xml @@ -25,9 +25,11 @@ </item> <!-- other settings --> <item + android:icon="@drawable/settings" android:id="@+id/drawer_settings" android:title="@string/title_settings"/> <item + android:icon="@drawable/info" android:id="@+id/drawer_about" android:title="@string/title_about"/> </menu> \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 3b5e70a97a94517eebe0bf7f8d1b7273fd45f931..7cdbd4ec2b08693dbea5f88f9c457baea7dae35e 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -46,4 +46,16 @@- @string/neen
<item>@string/dex</item> <item>@string/lef</item> </string-array> + + <string-array name="line_decorations"> + <item>@string/italics</item> + <item>@string/colour</item> + <item>@string/none</item> + </string-array> + + <string-array name="line_decorations_values"> + <item>italics</item> + <item>colour</item> + <item>none</item> + </string-array> </resources> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8e5ca43fe47402d84cefdf881ac378ccd664757d..5544a08fa8e80201a2b7dc37609f9afdfc7921d9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -29,7 +29,7 @@You are offline. Connect to the Internet <string name="error_gps">Cannot obtain current location</string> <string name="no_departures">No departures</string> <string name="waiting_position">waiting for position</string> - <string name="vehicle_headsign">%1$s » %2$s</string> + <string name="vehicle_headsign"><annotation decoration="apply"><annotation arg="0">%1$s</annotation></annotation> » <annotation arg="1">%2$s</annotation></string> <string name="distance_in_m">%1$s m</string> <plurals name="distance_in_m_cd"> <item quantity="one">%1$d metre</item> @@ -131,6 +131,7 @@momentarily <string name="departure_departed">departed</string> <string name="departure_now">now</string> <string name="at_time">at %1$02d:%2$02d</string> + <string name="about_time">about %1$02d:%2$02d</string> <string name="at_time_realtime">at %1$02d:%2$02d:%3$02d</string> <string name="on_demand">on demand</string> <string name="no_boarding">no boarding</string> @@ -146,6 +147,10 @@Results for ‘%1$s’ <string name="bimba_server_address_hint">Server</string> <string name="bimba_server_token_hint">Token</string> <string name="realtime_content_description">departure is realtime</string> + <!-- cf timepoint field in https://gtfs.org/schedule/reference/#stop_timestxt --> + <string name="exact_content_description">departure time is exact from schedule</string> + <!-- cf timepoint field in https://gtfs.org/schedule/reference/#stop_timestxt --> + <string name="inexact_content_description">departure time is approximate from schedule</string> <string name="wheelchair_content_description">vehicle is wheelchair accessible</string> <string name="air_condition_content_description">air conditioning</string> <string name="bicycles_allowed_content_description">bicycles allowed</string> @@ -259,4 +264,8 @@neen <string name="dex">dex</string> <string name="lef">lef</string> <string name="filtered_stop_question">Do you want to save a favourite filtered with selected lines?</string> + <string name="none">none</string> + <string name="italics">italics</string> + <string name="colour">colour</string> + <string name="line_decorations">Line name decorations</string> </resources> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 0cd1a0dacf54562ef83c5f01f304f305c18a6ec6..23ea65341109cbdcd89d71536547c76ec2212e18 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -9,7 +9,7 @@Karte <string name="home_fab_description">GPS-Symbol</string> <string name="title_activity_results">Ergebnisse</string> <string name="continue_">Fortsetzen</string> - <string name="vehicle_headsign">%1$s » %2$s</string> + <string name="vehicle_headsign"><annotation decoration="apply"><annotation arg="0">%1$s</annotation></annotation> » <annotation arg="1">%2$s</annotation></string> <string name="speed_in_km_per_h">%1$s km/h</string> <string name="congestion_unknown">unbekannt</string> <string name="congestion_congestion">Stau</string> diff --git a/app/src/main/res/values-en-rUS/strings.xml b/app/src/main/res/values-en-rUS/strings.xml index 8afbdd1697a0c2c92063444971b7bb220891b8e1..2deff940846040ba2348cc2cd33de82f6664e315 100644 --- a/app/src/main/res/values-en-rUS/strings.xml +++ b/app/src/main/res/values-en-rUS/strings.xml @@ -26,7 +26,7 @@You are offline. Connect to the Internet <string name="error_gps">Cannot obtain current location</string> <string name="no_departures">No departures</string> <string name="waiting_position">waiting for position</string> - <string name="vehicle_headsign">%1$s » %2$s</string> + <string name="vehicle_headsign"><annotation decoration="apply"><annotation arg="0">%1$s</annotation></annotation> » <annotation arg="1">%2$s</annotation></string> <string name="distance_in_m">%1$s m</string> <plurals name="distance_in_m_cd"> <item quantity="one">%1$d meter</item> diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 681fc303bc0dd98da77ad08144d901815fb93f97..1a44d63c4dfbb2e513512abbbe81adabb33a2ef4 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -16,7 +16,7 @@Il y a eu une erreur sur le serveur. Réessayez plus tard <string name="error_connecting">Erreur lors de la connection au serveur. Réessayez plus tard</string> <string name="error_unknown">Erreur inconnue</string> <string name="waiting_position">En attente de la position</string> - <string name="vehicle_headsign">%1$s » %2$s</string> + <string name="vehicle_headsign"><annotation decoration="apply"><annotation arg="0">%1$s</annotation></annotation> » <annotation arg="1">%2$s</annotation></string> <string name="congestion_unknown">Inconnu</string> <string name="congestion_smooth">Fluide</string> <string name="occupancy_standing_only">Uniquement debout</string> diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 69ecbb6d8a8a72b7e4f4af3003ecdcb28aebaf0a..9b4c97506c9d76ed958272f6fa3adac7d6357eb4 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -25,7 +25,7 @@Sei offline. Collega al’Internet <string name="error_gps">Non è possibile ottenere la posizione corrente</string> <string name="no_departures">Nessune partenze</string> <string name="waiting_position">In attesa della posizione</string> - <string name="vehicle_headsign">%1$s » %2$s</string> + <string name="vehicle_headsign"><annotation decoration="apply"><annotation arg="0">%1$s</annotation></annotation> » <annotation arg="1">%2$s</annotation></string> <string name="vehicle_headsign_content_description">%1$s verso %2$s</string> <string name="speed_in_km_per_h">%1$s km/h</string> <string name="congestion_unknown">sconosciuta</string> diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index c91cb8c9b197de575f215cf9b77488998cebbdc7..4725a9872ad279a61f8db367a6fa5641a30414e8 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -25,7 +25,7 @@Brak połączenia z Internetem <string name="error_gps">Nie można uzyskać bierzącej pozycji</string> <string name="no_departures">Brak odjazdów</string> <string name="waiting_position">oczekiwanie na pozycję</string> - <string name="vehicle_headsign">%1$s » %2$s</string> + <string name="vehicle_headsign"><annotation decoration="apply"><annotation arg="0">%1$s</annotation></annotation> » <annotation arg="1">%2$s</annotation></string> <string name="vehicle_headsign_content_description">%1$s w kierunku przystanku %2$s</string> <string name="speed_in_km_per_h">%1$s km/h</string> <string name="congestion_unknown">nieznane</string> diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index ab4959ff16b28aba10d9e4f2e244473c76f04fe2..4d40eb2a6f5b696bc91d93df8492454c72f5f80b 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -21,4 +21,16 @@ app:icon="@drawable/download" app:key="download_cities_list" app:title="Update cities list now" /> </PreferenceCategory> + + <PreferenceCategory app:title="Appearance"> + <ListPreference + app:defaultValue="italics" + app:entries="@array/line_decorations" + app:entryValues="@array/line_decorations_values" + app:icon="@drawable/vehicle" + app:key="line_decoration" + app:title="@string/line_decorations" + app:useSimpleSummaryProvider="true" + /> + </PreferenceCategory> </PreferenceScreen> \ No newline at end of file