Author: Adam Evyčędo <git@apiote.xyz>
Merge branch 'develop'
%!v(PANIC=String method: strings: negative Repeat count)
diff --git a/.gitignore b/.gitignore index 73d061c3eff9885fd9b5f102f37943513d0b118f..51ff5c25c1cacc26bc5d708f8334716cf8fb77a3 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,4 @@ converter/local/*.db converter/local/metadata.yml converter/local/__pycache__ converter/local/config.py +.kotlin diff --git a/README.adoc b/README.adoc index 0e385ff83cfed168c84862a4776cf1669e2959ad..9fd6689891dbe5915ae419d699d378944a4df0c4 100644 --- a/README.adoc +++ b/README.adoc @@ -4,7 +4,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later = Bimba Adam Evyčędo <me@apiote.xyz> -v3.7.0 2024-10-15 +v3.7.1 2024-11-30 :toc: Bimba is a FLOSS public transport passenger companion; a timetable in your pocket. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2048280d5c542d1f7157d718aa9dc8d64c8fb584..fa1aa641706e77412d05ae850be974e2a8165252 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -11,19 +11,19 @@ } android { namespace = "xyz.apiote.bimba.czwek" - compileSdk = 34 // https://gitlab.com/fdroid/fdroiddata/-/issues/3299#note_1989808414 - buildToolsVersion = - "34.0.0" // https://gitlab.com/fdroid/fdroiddata/-/issues/3299#note_1989808414 + // NOTE apksigner with `--alignment-preserved` https://gitlab.com/fdroid/fdroiddata/-/issues/3299#note_1989808414 + compileSdk = 35 + buildToolsVersion = "35.0.0" defaultConfig { applicationId = "xyz.apiote.bimba.czwek" minSdk = 21 targetSdk = 35 - versionCode = 32 - versionName = "3.7.0" + versionCode = 33 + versionName = "3.7.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - resourceConfigurations += listOf("en", "pl", "it", "de", "fr", "en-rUS") + resourceConfigurations += listOf("en", "de", "en-rGB", "en-rUS", "et", "fr", "it", "pl") } buildTypes { @@ -39,8 +39,8 @@ resValue("string", "applicationId", applicationId) } compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 isCoreLibraryDesugaringEnabled = true } @@ -50,26 +50,26 @@ } } dependencies { - implementation("androidx.core:core-ktx:1.13.1") + implementation("androidx.core:core-ktx:1.15.0") implementation("androidx.appcompat:appcompat:1.7.0") implementation("com.google.android.material:material:1.12.0") - implementation("androidx.constraintlayout:constraintlayout:2.1.4") - implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.6") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.6") - implementation("androidx.navigation:navigation-fragment-ktx:2.8.2") - implementation("androidx.navigation:navigation-ui-ktx:2.8.2") + implementation("androidx.constraintlayout:constraintlayout:2.2.0") + implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.7") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7") + implementation("androidx.navigation:navigation-fragment-ktx:2.8.4") + implementation("androidx.navigation:navigation-ui-ktx:2.8.4") implementation("androidx.legacy:legacy-support-v4:1.0.0") implementation("androidx.core:core-splashscreen:1.0.1") implementation("com.google.openlocationcode:openlocationcode:1.0.4") implementation("org.osmdroid:osmdroid-android:6.1.20") implementation("org.yaml:snakeyaml:2.3") - implementation("androidx.activity:activity-ktx:1.9.2") + implementation("androidx.activity:activity-ktx:1.9.3") implementation("com.otaliastudios:zoomlayout:1.9.0") implementation("dev.bandb.graphview:graphview:0.8.1") implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3") implementation("com.github.jershell:kbson:0.5.0") implementation("androidx.preference:preference-ktx:1.2.1") - implementation("androidx.work:work-runtime-ktx:2.9.1") + implementation("androidx.work:work-runtime-ktx:2.10.0") implementation("com.github.doyaaaaaken:kotlin-csv-jvm:1.10.0") implementation("commons-io:commons-io:2.17.0") implementation("com.google.guava:guava:33.3.1-android") @@ -77,7 +77,7 @@ implementation(project(":fruchtfleisch")) implementation("ch.acra:acra-http:5.11.4") implementation("ch.acra:acra-notification:5.11.4") - coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.2") + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.3") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.2.1") diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/transitousDepartures.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/transitousDepartures.kt index 66fa6ae249f756a186b7405f5794b29726efd1db..3c52446a49d0db59620b89fa7ac64a29bd774cf5 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/api/transitousDepartures.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/transitousDepartures.kt @@ -12,16 +12,15 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import xyz.apiote.bimba.czwek.R import xyz.apiote.bimba.czwek.api.responses.ErrorResponse -import xyz.apiote.bimba.czwek.repo.Alert import xyz.apiote.bimba.czwek.repo.Colour import xyz.apiote.bimba.czwek.repo.CongestionLevel -import xyz.apiote.bimba.czwek.repo.Departure +import xyz.apiote.bimba.czwek.repo.Event import xyz.apiote.bimba.czwek.repo.LineStub import xyz.apiote.bimba.czwek.repo.LineType import xyz.apiote.bimba.czwek.repo.OccupancyStatus import xyz.apiote.bimba.czwek.repo.Position import xyz.apiote.bimba.czwek.repo.Stop -import xyz.apiote.bimba.czwek.repo.StopDepartures +import xyz.apiote.bimba.czwek.repo.StopEvents import xyz.apiote.bimba.czwek.repo.TrafficResponseException import xyz.apiote.bimba.czwek.repo.Vehicle import xyz.apiote.bimba.czwek.units.Mps @@ -37,7 +36,7 @@ context: Context, stop: String, date: LocalDate?, limit: Int? -): StopDepartures { +): StopEvents { if (!isNetworkAvailable(context)) { throw TrafficResponseException(0, "", Error(0, R.string.error_offline, R.drawable.error_net)) } @@ -75,7 +74,7 @@ throw TrafficResponseException(result.error.statusCode, "", result.error) } } else { return withContext(Dispatchers.IO) { - val departures = mutableListOf<Departure>() + val events = mutableListOf<Event>() var stopID = "" var stopName = "" var latitude = 0.0 @@ -190,10 +189,17 @@ ZonedDateTime.ofInstant( Instant.ofEpochSecond(eventTimestamp), ZoneId.systemDefault() ) - departures.add( - Departure( - ID = hash, - time = Time( + events.add( + Event( + id = hash, + arrivalTime = Time( + t.hour.toUInt(), + t.minute.toUInt(), + t.second.toUInt(), + (t.dayOfYear - ZonedDateTime.now().dayOfYear).toByte(), + ZoneId.systemDefault().id + ), + departureTime = Time( t.hour.toUInt(), t.minute.toUInt(), t.second.toUInt(), @@ -247,8 +253,8 @@ } } } - return@withContext StopDepartures( - departures, + return@withContext StopEvents( + events, Stop(stopID, stopName, stopName, "", "transitous", Position(latitude, longitude), listOf()), listOf() ) diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/Favourites.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/Favourites.kt index 2b1d50a476c8181b6758489d60b61fe772080d09..11c0a85d49513a4f0720a5ca7a1854bc429b73c9 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/Favourites.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/Favourites.kt @@ -14,7 +14,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import xyz.apiote.bimba.czwek.R import xyz.apiote.bimba.czwek.departures.DeparturesActivity -import xyz.apiote.bimba.czwek.repo.Departure +import xyz.apiote.bimba.czwek.repo.Event import xyz.apiote.bimba.czwek.repo.Favourite import java.time.ZoneId import java.time.ZonedDateTime @@ -23,7 +23,7 @@ import java.util.Optional class BimbaFavouritesAdapter( private var favourites: List<Favourite>, - private var departures: Map<String, Optional<Departure>>, + private var departures: Map<String, Optional<Event>>, private val inflater: LayoutInflater, private val context: Context ) : @@ -34,9 +34,9 @@ private set inner class DiffUtilCallback( private val oldFavourites: List<Favourite>, - private val oldDepartures: Map<String, Optional<Departure>?>, + private val oldDepartures: Map<String, Optional<Event>?>, private val newFavourites: List<Favourite>, - private val newDepartures: Map<String, Optional<Departure>?> + private val newDepartures: Map<String, Optional<Event>?> ) : DiffUtil.Callback() { override fun getOldListSize() = oldFavourites.size @@ -57,9 +57,9 @@ return false } val favouritesSame = oldFav.feedName == newFav.feedName && - oldFav.stopName == newFav.stopName && - oldFav.sequence == newFav.sequence && - oldFav.lines == newFav.lines + oldFav.stopName == newFav.stopName && + oldFav.sequence == newFav.sequence && + oldFav.lines == newFav.lines if (!favouritesSame) { return false @@ -73,14 +73,14 @@ if ((oldDeparture!!.isEmpty && !newDeparture!!.isEmpty) || (!oldDeparture!!.isEmpty && newDeparture!!.isEmpty)) { return false } - return oldDeparture!!.get().ID == newDeparture!!.get().ID && - oldDeparture!!.get().vehicle.Line == newDeparture!!.get().vehicle.Line && - oldDeparture!!.get().vehicle.Headsign == newDeparture!!.get().vehicle.Headsign && - oldDeparture!!.get().statusText( - context, - false, - lastUpdate - ) == newDeparture!!.get().statusText(context, false) + return oldDeparture!!.get().id == newDeparture!!.get().id && + oldDeparture!!.get().vehicle.Line == newDeparture!!.get().vehicle.Line && + oldDeparture!!.get().vehicle.Headsign == newDeparture!!.get().vehicle.Headsign && + oldDeparture!!.get().statusText( + context, + false, + lastUpdate + ) == newDeparture!!.get().statusText(context, false) } } @@ -111,7 +111,7 @@ this.favourites = favourites diff.dispatchUpdatesTo(this) } - fun updateDepartures(departures: Map<String, Optional<Departure>>) { + fun updateDepartures(departures: Map<String, Optional<Event>>) { this.departures = departures notifyDataSetChanged() lastUpdate = ZonedDateTime.now() @@ -151,6 +151,10 @@ class FavouriteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val root: View = itemView.findViewById(R.id.favourite) val feedName: TextView = itemView.findViewById(R.id.feed_name) val lineIcon: ImageView = itemView.findViewById(R.id.line_icon) + val arrivalStatus: TextView = itemView.findViewById(R.id.arrival_status) + val arrivalTime: TextView = itemView.findViewById(R.id.arrival_time) + val arrivalTimeFull: TextView = itemView.findViewById(R.id.arrival_full_time) + val departureStatus: TextView = itemView.findViewById(R.id.departure_status) val departureTime: TextView = itemView.findViewById(R.id.departure_time) val departureTimeFull: TextView = itemView.findViewById(R.id.departure_full_time) val lineName: TextView = itemView.findViewById(R.id.departure_line) @@ -162,33 +166,32 @@ fun bind( favourite: Favourite, holder: FavouriteViewHolder, context: Context, - departure: Optional<Departure>? + event: Optional<Event>? ) { - if (departure == null) { + if (event == null) { holder.feedName.text = favourite.feedName holder.stopHeadline.text = favourite.stopName holder.lineIcon.setImageDrawable(null) holder.lineName.text = context.getString(R.string.loading) - holder.departureTime.text = "" - holder.departureTimeFull.text = "" + holder.arrivalTime.text = "" + holder.arrivalTimeFull.text = "" holder.headsign.text = "" - } else if (departure.isEmpty) { + } else if (event.isEmpty) { holder.feedName.text = favourite.feedName holder.stopHeadline.text = favourite.stopName holder.lineIcon.setImageDrawable(null) holder.lineName.text = context.getString(R.string.no_departures).lowercase() - holder.departureTime.text = "" - holder.departureTimeFull.text = "" + holder.arrivalTime.text = "" + holder.arrivalTimeFull.text = "" holder.headsign.text = "" } else { - val vehicle = departure.get().vehicle + val statusTexts = event.get().statusText(context, false) + val vehicle = event.get().vehicle holder.feedName.text = favourite.feedName holder.stopHeadline.text = favourite.stopName holder.lineIcon.setImageDrawable(vehicle.Line.icon(context)) holder.lineIcon.contentDescription = vehicle.Line.kind.name holder.lineName.text = vehicle.Line.name - holder.departureTime.text = departure.get().statusText(context, false) - holder.departureTimeFull.text = departure.get().timeString(context) holder.headsign.text = context.getString(R.string.departure_headsign, vehicle.Headsign) holder.headsign.contentDescription = @@ -196,10 +199,87 @@ context.getString( R.string.departure_headsign_content_description, vehicle.Headsign ) + + with(event.get()) { + if (arrivalTime == departureTime) { + holder.arrivalStatus.visibility = View.GONE + holder.arrivalTime.visibility = View.GONE + holder.arrivalTimeFull.visibility = View.GONE + holder.departureTime.apply { + text = statusTexts.second + visibility = View.VISIBLE + } + holder.departureTimeFull.apply { + text = departureTimeString(context) + visibility = View.VISIBLE + } + if (!exact) { + holder.departureStatus.apply { + text = context.getString(R.string.approximately) + visibility = View.VISIBLE + } + } else { + holder.departureStatus.visibility = View.GONE + } + } else { + if (arrivalTime != null) { + holder.arrivalTimeFull.apply { + visibility = View.VISIBLE + text = arrivalTimeString(context) + } + holder.arrivalTime.apply { + visibility = View.VISIBLE + text = statusTexts.first + } + holder.arrivalStatus.apply { + visibility = View.VISIBLE + text = if (!exact) { + context.getString(R.string.arrival_approximate) + } else { + context.getString(R.string.arrival) + } + } + } else { + holder.arrivalStatus.visibility = View.GONE + holder.arrivalTime.visibility = View.GONE + holder.arrivalTimeFull.visibility = View.GONE + } + if (departureTime != null) { + holder.departureTimeFull.apply { + visibility = View.VISIBLE + text = departureTimeString(context) + } + holder.departureTime.apply { + visibility = View.VISIBLE + text = statusTexts.second + } + holder.departureStatus.apply { + visibility = View.VISIBLE + text = if (!exact) { + context.getString(R.string.departure_approximate) + } else { + context.getString(R.string.departure) + } + } + } else { + holder.departureStatus.visibility = View.GONE + holder.departureTime.visibility = View.GONE + holder.departureTimeFull.visibility = View.GONE + } + } + } } holder.root.setOnClickListener { - context.startActivity(DeparturesActivity.getIntent(context, favourite.stopCode, favourite.stopName, favourite.feedID, favourite.lines.toTypedArray())) + context.startActivity( + DeparturesActivity.getIntent( + context, + favourite.stopCode, + favourite.stopName, + favourite.feedID, + favourite.lines.toTypedArray() + ) + ) } } } diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeViewModel.kt index ba6da66f9308e7dc91bd81aca46cff37c3dffee1..def65cf9bf6e3e4d1f37c37e65d5121123a5824d 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeViewModel.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeViewModel.kt @@ -18,7 +18,7 @@ import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch -import xyz.apiote.bimba.czwek.repo.Departure +import xyz.apiote.bimba.czwek.repo.Event import xyz.apiote.bimba.czwek.repo.Favourite import xyz.apiote.bimba.czwek.repo.FeedInfo import xyz.apiote.bimba.czwek.repo.OfflineRepository @@ -36,8 +36,8 @@ var feeds: Map? = null var feedsSettings: FeedsSettings? = null private val mutableFavourites = MutableLiveData<List<Favourite>>() val favourites: LiveData<List<Favourite>> = mutableFavourites - private val mutableDepartures = MutableLiveData<Map<String, Optional<Departure>>>() - val departures: LiveData<Map<String, Optional<Departure>>> = mutableDepartures + private val mutableDepartures = MutableLiveData<Map<String, Optional<Event>>>() + val departures: LiveData<Map<String, Optional<Event>>> = mutableDepartures fun getQueryables(query: String, context: Context) { viewModelScope.launch { @@ -89,10 +89,10 @@ context, 12 // XXX heuristics ) stopDepartures?.let { sDs -> - if (sDs.departures.isEmpty()) { + if (sDs.events.isEmpty()) { Pair(favourite.feedID+favourite.stopCode, Optional.empty()) } else { - Pair(favourite.feedID+favourite.stopCode, Optional.ofNullable(sDs.departures.find { departure -> + Pair(favourite.feedID+favourite.stopCode, Optional.ofNullable(sDs.events.find { departure -> favourite.lines.isEmpty() or favourite.lines.contains( departure.vehicle.Line.name ) 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 6aa86b0cb2362798e410558411e5229ae8ba873e..a9ff0719d69c398d56d1f3e06ad2aa3cc8072187 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 @@ -73,7 +73,7 @@ vehicle.Headsign ) } - content.findViewById<TextView>(R.id.time).visibility = View.GONE + content.findViewById<TextView>(R.id.arrival_time).visibility = View.GONE content.findViewById<TextView>(R.id.local_time).visibility = View.GONE content.findViewById<MapView>(R.id.map).visibility = View.GONE 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 17c08de21676990de2632a77c932c099454c4626..01f592aa9c53a29de8ef478f6d1ff9f504d97335 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 @@ -34,13 +34,12 @@ import org.osmdroid.views.MapView import org.osmdroid.views.overlay.Marker import org.osmdroid.views.overlay.TilesOverlay import org.osmdroid.views.overlay.gestures.RotationGestureOverlay -import org.w3c.dom.Text import xyz.apiote.bimba.czwek.R import xyz.apiote.bimba.czwek.dpToPixelI import xyz.apiote.bimba.czwek.repo.Alert import xyz.apiote.bimba.czwek.repo.CongestionLevel -import xyz.apiote.bimba.czwek.repo.Departure -import xyz.apiote.bimba.czwek.repo.DepartureItem +import xyz.apiote.bimba.czwek.repo.Event +import xyz.apiote.bimba.czwek.repo.EventItem import xyz.apiote.bimba.czwek.repo.OccupancyStatus import xyz.apiote.bimba.czwek.repo.Vehicle import xyz.apiote.bimba.czwek.units.UnitSystem @@ -50,75 +49,118 @@ class BimbaDepartureViewHolder(itemView: View) : ViewHolder(itemView) { val root: View = itemView.findViewById(R.id.departure) val lineIcon: ImageView = itemView.findViewById(R.id.line_icon) + val arrivalTime: TextView = itemView.findViewById(R.id.arrival_time) + val arrivalStatus: TextView = itemView.findViewById(R.id.arrival_status) val departureTime: TextView = itemView.findViewById(R.id.departure_time) + val departureStatus: TextView = itemView.findViewById(R.id.departure_status) 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) + val eventStatus: ImageView = itemView.findViewById(R.id.event_status) companion object { fun bind( - departure: Departure, + event: Event, holder: BimbaDepartureViewHolder?, context: Context?, showAsTime: Boolean, - onClickListener: (Departure) -> Unit, + onClickListener: (Event) -> Unit, showingTerminusArrivals: String ) { holder?.root?.setOnClickListener { - onClickListener(departure) + onClickListener(event) } - holder?.lineIcon?.setImageDrawable(departure.vehicle.Line.icon(context!!)) - holder?.lineIcon?.contentDescription = departure.vehicle.Line.kind.name - holder?.lineName?.text = departure.vehicle.Line.name + holder?.lineIcon?.setImageDrawable(event.vehicle.Line.icon(context!!)) + holder?.lineIcon?.contentDescription = event.vehicle.Line.kind.name + holder?.lineName?.text = event.vehicle.Line.name holder?.headsign?.text = - context?.getString(R.string.departure_headsign, departure.vehicle.Headsign) + context?.getString(R.string.departure_headsign, event.vehicle.Headsign) holder?.headsign?.contentDescription = context?.getString( R.string.departure_headsign_content_description, - departure.vehicle.Headsign + event.vehicle.Headsign ) when { - departure.isRealtime -> { - holder?.timeStatus?.setImageResource(R.drawable.radar) - holder?.timeStatus?.contentDescription = - context?.getString(R.string.realtime_content_description) - holder?.timeStatus?.let { + event.isRealtime -> { + holder?.eventStatus?.let { + it.contentDescription = + context?.getString(R.string.realtime_content_description) + it.setImageResource(R.drawable.radar) TooltipCompat.setTooltipText( it, context?.getString(R.string.realtime_content_description) ) + // TODO all at the same time with setCurrentFraction based on wall clock + /*ObjectAnimator.ofPropertyValuesHolder(it, PropertyValuesHolder.ofFloat("alpha", 0.0f)) + .apply { + setDuration(1000) + repeatCount = ObjectAnimator.INFINITE + repeatMode = ObjectAnimator.REVERSE + } + .start()*/ } } - departure.exact -> { - holder?.timeStatus?.setImageResource(R.drawable.calendar) - holder?.timeStatus?.contentDescription = - context?.getString(R.string.exact_content_description) - holder?.timeStatus?.let { + event.exact -> { + // FIXME clear animation + holder?.eventStatus?.let { + it.setImageResource(R.drawable.calendar) + it.contentDescription = + context?.getString(R.string.schedule_content_description) TooltipCompat.setTooltipText( it, - context?.getString(R.string.exact_content_description) + context?.getString(R.string.schedule_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) - ) + val statusTexts = event.statusText(context, showAsTime) + if (event.arrivalTime == event.departureTime) { + if (!event.exact) { + holder?.arrivalStatus?.apply{ + visibility = View.VISIBLE + text = context?.getString(R.string.approximately) + } + } else { + holder?.arrivalStatus?.visibility = View.INVISIBLE + } + holder?.arrivalTime?.apply{ + text = statusTexts.second + visibility = View.VISIBLE + } + holder?.departureStatus?.visibility = View.GONE + holder?.departureTime?.visibility = View.GONE + } else { + if (statusTexts.first != null) { + holder?.arrivalTime?.visibility = View.VISIBLE + holder?.arrivalTime?.text = statusTexts.first + holder?.arrivalStatus?.visibility = View.VISIBLE + holder?.arrivalStatus?.text = if (!event.exact) { + context?.getString(R.string.arrival_approximate) + } else { + context?.getString(R.string.arrival) } + } else { + holder?.arrivalTime?.visibility = View.GONE + holder?.arrivalStatus?.visibility = View.GONE + } + if (statusTexts.second != null) { + holder?.departureTime?.visibility = View.VISIBLE + holder?.departureTime?.text = statusTexts.second + holder?.departureStatus?.visibility = View.VISIBLE + holder?.departureStatus?.text = if (!event.exact) { + context?.getString(R.string.departure_approximate) + } else { + context?.getString(R.string.departure) + } + } else { + holder?.departureTime?.visibility = View.GONE + holder?.departureStatus?.visibility = View.GONE } } - - holder?.departureTime?.text = departure.statusText(context, showAsTime) holder?.root?.alpha = - if (departure.terminusArrival && showingTerminusArrivals == BimbaDeparturesAdapter.TERMINUS_ARRIVAL_GREY_OUT) { + if (event.terminusArrival && showingTerminusArrivals == BimbaDeparturesAdapter.TERMINUS_ARRIVAL_GREY_OUT) { .5f } else { 1f @@ -160,8 +202,8 @@ class BimbaDeparturesAdapter( private val inflater: LayoutInflater, private val context: Context?, - private var items: List<DepartureItem>, - private val onClickListener: ((Departure) -> Unit), + private var items: List<EventItem>, + private val onClickListener: ((Event) -> Unit), ) : RecyclerView.Adapter<ViewHolder>() { @@ -188,8 +230,8 @@ private set private var showAsTime: Boolean = false inner class DiffUtilCallback( - private val oldDepartures: List<DepartureItem>, - private val newDepartures: List<DepartureItem>, + private val oldDepartures: List<EventItem>, + private val newDepartures: List<EventItem>, private val showAsTimeChanged: Boolean, ) : DiffUtil.Callback() { override fun getOldListSize() = oldDepartures.size @@ -197,23 +239,23 @@ override fun getNewListSize() = newDepartures.size override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) = - (oldDepartures[oldItemPosition].departure?.ID - ?: ALERT_ITEM_ID) == (newDepartures[newItemPosition].departure?.ID ?: ALERT_ITEM_ID) + (oldDepartures[oldItemPosition].event?.id + ?: ALERT_ITEM_ID) == (newDepartures[newItemPosition].event?.id ?: ALERT_ITEM_ID) 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.terminusArrival && - 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( + return if (oldDeparture.event != null && newDeparture.event != null) { + !oldDeparture.event.terminusArrival && + oldDeparture.event.terminusArrival == newDeparture.event.terminusArrival && + oldDeparture.event.exact == newDeparture.event.exact && + oldDeparture.event.vehicle.Line == newDeparture.event.vehicle.Line && + oldDeparture.event.vehicle.Headsign == newDeparture.event.vehicle.Headsign && + oldDeparture.event.statusText( context, false, lastUpdate - ) == newDeparture.departure.statusText(context, false) && !showAsTimeChanged + ) == newDeparture.event.statusText(context, false) && !showAsTimeChanged } else if (oldDeparture.alert.isNotEmpty() && newDeparture.alert.isEmpty()) { oldDeparture.alert == newDeparture.alert } else { @@ -226,12 +268,12 @@ private var departuresPositions: MutableMap = HashMap() init { items.forEachIndexed { i, departure -> - departuresPositions[departure.departure?.ID ?: ALERT_ITEM_ID] = i + departuresPositions[departure.event?.id ?: ALERT_ITEM_ID] = i } } override fun getItemViewType(position: Int): Int { - return if (items[position].departure != null) { + return if (items[position].event != null) { 0 } else { 1 @@ -251,7 +293,7 @@ override fun onBindViewHolder(holder: ViewHolder, position: Int) { if (holder is BimbaDepartureViewHolder) { BimbaDepartureViewHolder.bind( - items[position].departure!!, + items[position].event!!, holder, context, showAsTime, @@ -265,7 +307,7 @@ } override fun getItemCount(): Int = items.size - fun get(id: String): DepartureItem? { + fun get(id: String): EventItem? { val position = departuresPositions[id] return if (position == null) { null @@ -275,7 +317,7 @@ } } fun update( - departures: List<DepartureItem>, + departures: List<EventItem>, showAsTime: Boolean, areNewObserved: Boolean = false, leaveAlert: Boolean = false @@ -287,7 +329,7 @@ departures } val newPositions: MutableMap<String, Int> = HashMap() newDepartures.forEachIndexed { i, departure -> - newPositions[departure.departure?.ID ?: ALERT_ITEM_ID] = i + newPositions[departure.event?.id ?: ALERT_ITEM_ID] = i } val diff = DiffUtil.calculateDiff( DiffUtilCallback( @@ -312,7 +354,7 @@ update(this.items, showAsTime) } } -class DepartureBottomSheet(private var departure: Departure) : BottomSheetDialogFragment() { +class DepartureBottomSheet(private var event: Event) : BottomSheetDialogFragment() { companion object { const val TAG = "DepartureBottomSheet" } @@ -329,33 +371,69 @@ cancelCallback?.let { it() } } fun departureID(): String { - return departure.ID + return event.id } - fun update(departure: Departure) { - this.departure = departure + fun update(event: Event) { + this.event = event view?.let { context?.let { ctx -> setContent(it, ctx, true) } } } private fun setContent(view: View, ctx: Context, updating: Boolean = false) { view.apply { - findViewById<TextView>(R.id.time).text = departure.timeString(ctx) + if (event.arrivalTime == event.departureTime) { + if (!event.exact) { + findViewById<TextView>(R.id.arrival_status).apply { + visibility = View.VISIBLE + text = context.getString(R.string.approximately) + } + } else { + findViewById<TextView>(R.id.arrival_status).visibility = View.GONE + } + findViewById<TextView>(R.id.arrival_time).apply { + text = event.arrivalTimeString(ctx) + visibility = View.VISIBLE + } + findViewById<TextView>(R.id.departure_status).visibility = View.GONE + findViewById<TextView>(R.id.departure_time).visibility = View.GONE + } else { + if (event.arrivalTime != null) { + findViewById<TextView>(R.id.arrival_time).visibility = View.VISIBLE + findViewById<TextView>(R.id.arrival_time).text = event.arrivalTimeString(ctx) + findViewById<TextView>(R.id.arrival_status).visibility = View.VISIBLE + findViewById<TextView>(R.id.arrival_status).text = if (!event.exact) { + context?.getString(R.string.arrival_approximate) + } else { + context?.getString(R.string.arrival) + } + } + if (event.departureTime != null) { + findViewById<TextView>(R.id.departure_time).visibility = View.VISIBLE + findViewById<TextView>(R.id.departure_time).text = event.departureTimeString(ctx) + findViewById<TextView>(R.id.departure_status).visibility = View.VISIBLE + findViewById<TextView>(R.id.departure_status).text = if (!event.exact) { + context?.getString(R.string.departure_approximate) + } else { + context?.getString(R.string.departure) + } + } + } findViewById<TextView>(R.id.local_time).visibility = - if (departure.time.Zone == ZoneId.systemDefault().id) { + if (event.timeZone() == ZoneId.systemDefault().id) { View.GONE } else { View.VISIBLE } findViewById<ImageView>(R.id.rt_icon).apply { - visibility = if (departure.isRealtime) { + visibility = if (event.isRealtime) { View.VISIBLE } else { View.GONE } } findViewById<ImageView>(R.id.wheelchair_icon).apply { - visibility = if (departure.vehicle.let { + visibility = if (event.vehicle.let { it.getCapability(Vehicle.Capability.LOW_FLOOR) || it.getCapability(Vehicle.Capability.LOW_ENTRY) || it.getCapability( Vehicle.Capability.RAMP ) @@ -369,41 +447,41 @@ findViewById<TextView>(R.id.line).apply { contentDescription = getString( R.string.vehicle_headsign_content_description, - departure.vehicle.Line.name, - departure.vehicle.Headsign + event.vehicle.Line.name, + event.vehicle.Headsign ) text = getString( R.string.vehicle_headsign, - departure.vehicle.Line.name, - departure.vehicle.Headsign + event.vehicle.Line.name, + event.vehicle.Headsign ) } - departure.boardingText(ctx).let { + event.boardingText(ctx).let { findViewById<TextView>(R.id.boarding_text).text = it - findViewById<ImageView>(R.id.boarding_icon).visibility = if (it == "") { - View.GONE - } else { - View.VISIBLE - } + findViewById<ImageView>(R.id.boarding_icon).visibility = if (it == "") { + View.GONE + } else { + View.VISIBLE + } } UnitSystem.getSelected(requireContext()).let { us -> findViewById<TextView>(R.id.speed_text).apply { text = - us.toString(context, us.speedUnit(departure.vehicle.Speed)) + us.toString(context, us.speedUnit(event.vehicle.Speed)) contentDescription = - us.speedUnit(departure.vehicle.Speed).contentDescription(requireContext(), us.base) + us.speedUnit(event.vehicle.Speed).contentDescription(requireContext(), us.base) } } findViewById<LinearLayout>(R.id.congestion).visibility = - if (departure.vehicle.congestionLevel == CongestionLevel.UNKNOWN) View.GONE else View.VISIBLE - findViewById<TextView>(R.id.congestion_text).text = departure.vehicle.congestion(ctx) + if (event.vehicle.congestionLevel == CongestionLevel.UNKNOWN) View.GONE else View.VISIBLE + findViewById<TextView>(R.id.congestion_text).text = event.vehicle.congestion(ctx) findViewById<LinearLayout>(R.id.occupancy).visibility = - if (departure.vehicle.occupancyStatus == OccupancyStatus.UNKNOWN) View.GONE else View.VISIBLE - findViewById<TextView>(R.id.occupancy_text).text = departure.vehicle.occupancy(ctx) + if (event.vehicle.occupancyStatus == OccupancyStatus.UNKNOWN) View.GONE else View.VISIBLE + findViewById<TextView>(R.id.occupancy_text).text = event.vehicle.occupancy(ctx) findViewById<ImageView>(R.id.ac).let { TooltipCompat.setTooltipText( @@ -411,7 +489,7 @@ it, getString(R.string.air_condition_content_description) ) it.visibility = - if (departure.vehicle.getCapability(Vehicle.Capability.AC)) View.VISIBLE else View.GONE + if (event.vehicle.getCapability(Vehicle.Capability.AC)) View.VISIBLE else View.GONE } findViewById<ImageView>(R.id.bike).let { @@ -420,7 +498,7 @@ it, getString(R.string.bicycles_allowed_content_description) ) it.visibility = - if (departure.vehicle.getCapability(Vehicle.Capability.BIKE)) { + if (event.vehicle.getCapability(Vehicle.Capability.BIKE)) { View.VISIBLE } else { View.GONE @@ -433,7 +511,7 @@ it, getString(R.string.voice_announcements_content_description) ) it.visibility = - if (departure.vehicle.getCapability(Vehicle.Capability.VOICE)) { + if (event.vehicle.getCapability(Vehicle.Capability.VOICE)) { View.VISIBLE } else { View.GONE @@ -444,7 +522,7 @@ TooltipCompat.setTooltipText( ticketImage, getString(R.string.tickets_sold_content_description) ) - ticketImage.visibility = if (departure.vehicle.let { + ticketImage.visibility = if (event.vehicle.let { it.getCapability(Vehicle.Capability.TICKET_DRIVER) || it.getCapability(Vehicle.Capability.TICKET_MACHINE) }) { View.VISIBLE @@ -458,15 +536,15 @@ it, getString(R.string.usb_charging_content_description) ) it.visibility = - if (departure.vehicle.getCapability(Vehicle.Capability.USB_CHARGING)) { + if (event.vehicle.getCapability(Vehicle.Capability.USB_CHARGING)) { View.VISIBLE } else { View.GONE } } - if (departure.alerts.isNotEmpty()) { - findViewById<MaterialTextView>(R.id.alerts_text).text = departure.alerts.map { + if (event.alerts.isNotEmpty()) { + findViewById<MaterialTextView>(R.id.alerts_text).text = event.alerts.map { it.header.ifEmpty { getString(R.string.alert_header) } @@ -477,7 +555,7 @@ setOnClickListener { MaterialAlertDialogBuilder(context) .setTitle(R.string.alerts) .setPositiveButton(R.string.ok) { _, _ -> } - .setMessage(departure.alerts.map { it.description }.filter { it != "" } + .setMessage(event.alerts.map { it.description }.filter { it != "" } .joinToString(separator = "\n")) .show() } @@ -485,14 +563,14 @@ } } findViewById<MapView>(R.id.map).let { map -> - if (departure.vehicle.Position.isZero()) { + if (event.vehicle.Position.isZero()) { map.visibility = View.GONE return@let } map.controller.apply { GeoPoint( - departure.vehicle.location().latitude, - departure.vehicle.location().longitude + event.vehicle.location().latitude, + event.vehicle.location().longitude ).let { geoPoint -> if (updating) { animateTo( @@ -511,11 +589,11 @@ } val marker = Marker(map).apply { position = GeoPoint( - departure.vehicle.location().latitude, - departure.vehicle.location().longitude + event.vehicle.location().latitude, + event.vehicle.location().longitude ) setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER) - icon = context?.let { ctx -> departure.vehicle.icon(ctx, 2f) } + icon = context?.let { ctx -> event.vehicle.icon(ctx, 2f) } setOnClickListener {} } map.overlays.add(marker) 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 0b725721dcfca87b8b52eaa06e4407b36784c410..8ca35eb6214c46644d0d28ee8f635bd4054a37d5 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 @@ -28,6 +28,7 @@ import androidx.core.view.WindowInsetsCompat import androidx.core.view.updatePadding import androidx.lifecycle.ViewModelProvider import androidx.preference.PreferenceManager +import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.google.android.material.datepicker.MaterialDatePicker @@ -45,7 +46,7 @@ import xyz.apiote.bimba.czwek.databinding.ActivityDeparturesBinding import xyz.apiote.bimba.czwek.departures.BimbaDeparturesAdapter.Companion.TERMINUS_ARRIVAL_GREY_OUT import xyz.apiote.bimba.czwek.departures.BimbaDeparturesAdapter.Companion.TERMINUS_ARRIVAL_HIDE import xyz.apiote.bimba.czwek.departures.BimbaDeparturesAdapter.Companion.TERMINUS_ARRIVAL_SHOWING_KEY -import xyz.apiote.bimba.czwek.repo.DepartureItem +import xyz.apiote.bimba.czwek.repo.EventItem import xyz.apiote.bimba.czwek.repo.Favourite import xyz.apiote.bimba.czwek.repo.OfflineRepository import xyz.apiote.bimba.czwek.repo.Stop @@ -168,7 +169,7 @@ } viewModel.linesFilter.observe(this) { // TODO if is before we got departures, do nothing - val departures = viewModel.departures.value?.departures ?: emptyList() + val departures = viewModel.departures.value?.events ?: emptyList() updateItems(departures .filter { d -> it.values.all { !it } or (it[d.vehicle.Line.name] ?: false) @@ -177,20 +178,20 @@ .filter { d -> viewModel.showingTerminusArrivals != TERMINUS_ARRIVAL_HIDE || !d.terminusArrival } .filter { d -> - val t = LocalTime.of(d.time.Hour.toInt(), d.time.Minute.toInt()) + val t = LocalTime.of(d.filterTime().Hour.toInt(), d.filterTime().Minute.toInt()) t >= viewModel.startTime && t <= viewModel.endTime - }.map { DepartureItem(it) }, + }.map { EventItem(it) }, null, true ) } viewModel.departures.observe(this) { stopDepartures -> - val items = mutableListOf<DepartureItem>() + val items = mutableListOf<EventItem>() if (stopDepartures.alerts.isNotEmpty()) { - items.add(DepartureItem(stopDepartures.alerts)) + items.add(EventItem(stopDepartures.alerts)) } - items.addAll(stopDepartures.departures + items.addAll(stopDepartures.events .filter { d -> viewModel.linesFilter.value?.let { filter -> filter.values.all { !it } or (filter[d.vehicle.Line.name] ?: false) @@ -200,15 +201,15 @@ .filter { d -> viewModel.showingTerminusArrivals != TERMINUS_ARRIVAL_HIDE || !d.terminusArrival } .filter { d -> - val t = LocalTime.of(d.time.Hour.toInt(), d.time.Minute.toInt()) + val t = LocalTime.of(d.filterTime().Hour.toInt(), d.filterTime().Minute.toInt()) t >= viewModel.startTime && t <= viewModel.endTime - }.map { DepartureItem(it) }) + }.map { EventItem(it) }) updateItems(items, stopDepartures.stop) viewModel.openBottomSheet?.departureID()?.let { adapter.get(it) } - ?.let { it.departure?.let { departure -> viewModel.openBottomSheet?.update(departure) } } + ?.let { it.event?.let { departure -> viewModel.openBottomSheet?.update(departure) } } - val lines = stopDepartures.departures.map { it.vehicle.Line.name }.sortedWith { s1, s2 -> + val lines = stopDepartures.events.map { it.vehicle.Line.name }.sortedWith { s1, s2 -> val s1n = s1.toIntOrNull() val s2n = s2.toIntOrNull() if (s1n != null && s2n != null) { @@ -374,6 +375,7 @@ } } binding.departuresRecycler.layoutManager = LinearLayoutManager(this) + binding.departuresRecycler.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL)) binding.departuresRecycler.itemAnimator = null binding.departuresRecycler.addOnScrollListener( object : RecyclerView.OnScrollListener() { @@ -518,7 +520,7 @@ binding.errorText.visibility = View.GONE } private fun updateItems( - departures: List<DepartureItem>, + departures: List<EventItem>, stop: Stop?, leaveAlert: Boolean = false ) { diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesViewModel.kt index bd61194560e6a232a5754bbf33fa60b3ed03dc6f..21dbd04eefa862f93ad0f5ad95a0fc1ef48e80db 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesViewModel.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesViewModel.kt @@ -20,14 +20,14 @@ import xyz.apiote.bimba.czwek.repo.FeedInfo import xyz.apiote.bimba.czwek.repo.OfflineRepository import xyz.apiote.bimba.czwek.repo.OnlineRepository import xyz.apiote.bimba.czwek.repo.QrLocation -import xyz.apiote.bimba.czwek.repo.StopDepartures +import xyz.apiote.bimba.czwek.repo.StopEvents import xyz.apiote.bimba.czwek.repo.TrafficResponseException import java.time.LocalDate import java.time.LocalTime class DeparturesViewModel : ViewModel() { - private val _departures = MutableLiveData<StopDepartures>() - val departures: LiveData<StopDepartures> = _departures + private val _departures = MutableLiveData<StopEvents>() + val departures: LiveData<StopEvents> = _departures private val _error = MutableLiveData<Error>() val error: LiveData<Error> = _error var requestedItemsNumber = 12 @@ -64,7 +64,7 @@ context, requestedItemsNumber ) stopDepartures?.let { - if (stopDepartures.departures.isEmpty()) { + if (stopDepartures.events.isEmpty()) { val (string, image) = mapHttpError(44) throw TrafficResponseException(44, "", Error(44, string, image)) } 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 deleted file mode 100644 index 38a48a946c2048ad2fa19b5eb4fa169769287adc..0000000000000000000000000000000000000000 --- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt +++ /dev/null @@ -1,242 +0,0 @@ -// SPDX-FileCopyrightText: Adam Evyčędo -// -// SPDX-License-Identifier: GPL-3.0-or-later - -package xyz.apiote.bimba.czwek.repo - -import android.content.Context -import android.text.format.DateUtils -import xyz.apiote.bimba.czwek.R -import xyz.apiote.bimba.czwek.api.AlertCauseV1 -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.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 -import xyz.apiote.bimba.czwek.units.TGM -import xyz.apiote.bimba.czwek.units.UnitSystem -import java.time.Instant -import java.time.ZoneId -import java.time.ZonedDateTime -import java.time.format.DateTimeFormatter -import java.time.temporal.ChronoUnit - - -class DepartureItem { - private constructor(d: Departure?, a: List<Alert>) { - departure = d - alert = a - } - - constructor(d: Departure) : this(d, emptyList()) - constructor(a: List<Alert>) : this(null, a) - - val departure: Departure? - val alert: List<Alert> -} - -enum class AlertCause { - UNKNOWN, OTHER, TECHNICAL_PROBLEM, STRIKE, DEMONSTRATION, ACCIDENT, HOLIDAY, WEATHER, MAINTENANCE, - CONSTRUCTION, POLICE_ACTIVITY, MEDICAL_EMERGENCY; - - companion object { - fun of(type: AlertCauseV1): AlertCause { - return when (type) { - AlertCauseV1.UNKNOWN -> valueOf("UNKNOWN") - AlertCauseV1.OTHER -> valueOf("OTHER") - AlertCauseV1.TECHNICAL_PROBLEM -> valueOf("TECHNICAL_PROBLEM") - AlertCauseV1.STRIKE -> valueOf("STRIKE") - AlertCauseV1.DEMONSTRATION -> valueOf("DEMONSTRATION") - AlertCauseV1.ACCIDENT -> valueOf("ACCIDENT") - AlertCauseV1.HOLIDAY -> valueOf("HOLIDAY") - AlertCauseV1.WEATHER -> valueOf("WEATHER") - AlertCauseV1.MAINTENANCE -> valueOf("MAINTENANCE") - AlertCauseV1.CONSTRUCTION -> valueOf("CONSTRUCTION") - AlertCauseV1.POLICE_ACTIVITY -> valueOf("POLICE_ACTIVITY") - AlertCauseV1.MEDICAL_EMERGENCY -> valueOf("MEDICAL_EMERGENCY") - } - } - } -} - -enum class AlertEffect { - UNKNOWN, OTHER, NO_SERVICE, REDUCED_SERVICE, SIGNIFICANT_DELAYS, DETOUR, ADDITIONAL_SERVICE, - MODIFIED_SERVICE, STOP_MOVED, NONE, ACCESSIBILITY_ISSUE; - - companion object { - fun of(type: AlertEffectV1): AlertEffect { - return when (type) { - AlertEffectV1.UNKNOWN -> valueOf("UNKNOWN") - AlertEffectV1.OTHER -> valueOf("OTHER") - AlertEffectV1.NO_SERVICE -> valueOf("NO_SERVICE") - AlertEffectV1.REDUCED_SERVICE -> valueOf("REDUCED_SERVICE") - AlertEffectV1.SIGNIFICANT_DELAYS -> valueOf("SIGNIFICANT_DELAYS") - AlertEffectV1.DETOUR -> valueOf("DETOUR") - AlertEffectV1.ADDITIONAL_SERVICE -> valueOf("ADDITIONAL_SERVICE") - AlertEffectV1.MODIFIED_SERVICE -> valueOf("MODIFIED_SERVICE") - AlertEffectV1.STOP_MOVED -> valueOf("STOP_MOVED") - AlertEffectV1.NONE -> valueOf("NONE") - AlertEffectV1.ACCESSIBILITY_ISSUE -> valueOf("ACCESSIBILITY_ISSUE") - } - } - } -} - -data class Alert( - val header: String, - val description: String, - val url: String, - val cause: AlertCause, - val effect: AlertEffect -) { - constructor(a: AlertV1) : this( - a.header, - a.Description, - a.Url, - AlertCause.of(a.Cause), - AlertEffect.of(a.Effect) - ) -} - -data class StopDepartures( - val departures: List<Departure>, - val stop: Stop, - val alerts: List<Alert> -) - -data class Departure( - val ID: String, - val time: Time, - val status: ULong, - val isRealtime: Boolean, - val vehicle: Vehicle, - val boarding: UByte, - val alerts: List<Alert>, - val exact: Boolean, - val terminusArrival: Boolean -) { - - constructor(d: DepartureV1) : this( - d.ID, - d.time, - d.status, - d.isRealtime, - Vehicle(d.vehicle), - d.boarding, - emptyList(), - true, - false - ) - - constructor(d: DepartureV2) : this( - d.ID, - d.time, - d.status, - d.isRealtime, - Vehicle(d.vehicle), - d.boarding, - emptyList(), - true, - false - ) - - constructor(d: DepartureV3) : this( - d.ID, - d.time, - d.status.ordinal.toULong(), // TODO VehicleStatus - d.isRealtime, - Vehicle(d.vehicle), - d.boarding, - emptyList(), - true, - false - ) - - constructor(d: DepartureV4) : this( - d.ID, - d.time, - d.status.ordinal.toULong(), // TODO VehicleStatus - d.isRealtime, - Vehicle(d.vehicle), - d.boarding, - 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 { - val now = at ?: Instant.now().atZone(ZoneId.systemDefault()) - val departureTime = ZonedDateTime.of( - now.year, now.monthValue, now.dayOfMonth, - time.Hour.toInt(), time.Minute.toInt(), time.Second.toInt(), 0, ZoneId.of(time.Zone) - ).plus(time.DayOffset.toLong(), ChronoUnit.DAYS) - if (showAsTime) { - return departureTime.format(DateTimeFormatter.ofPattern("HH:mm")) - } - var r = status.toUInt() - if (departureTime.isBefore(now) && r < 3u) { - r = 0u - } - return when (r) { - 0u -> if (context != null && UnitSystem.getSelected(context) is TGM) { - val us = UnitSystem.getSelected(context) - us.toString( - context, - us.timeUnit(Second((departureTime.toEpochSecond() - now.toEpochSecond()).toInt())) - ) - } else { - DateUtils.getRelativeTimeSpanString( - departureTime.toEpochSecond() * 1000, - now.toEpochSecond() * 1000, - DateUtils.MINUTE_IN_MILLIS, - DateUtils.FORMAT_ABBREV_RELATIVE - ).toString() - } - - 1u -> context?.getString(R.string.departure_momentarily) ?: "momentarily" - 2u -> context?.getString(R.string.departure_now) ?: "now" - 3u -> context?.getString(R.string.departure_departed) ?: "departed" - else -> throw UnknownResourceVersionException("VehicleStatus/$r", 1u) - } - } - - fun timeString(context: Context): String { - return when { - isRealtime -> context.getString( - R.string.at_time_realtime, time.Hour.toInt(), time.Minute.toInt(), time.Second.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()) - } - } - - fun boardingText(context: Context): String { - // todo [3.x] probably should take into account (on|off)-boarding only, on demand - return when { - boarding == (0b0000_0000).toUByte() -> context.getString(R.string.no_boarding) - boarding == (0b1111_1111).toUByte() -> "" // unknown - boarding.and(0b0011_0011u) == (0b0000_0001).toUByte() -> context.getString(R.string.on_boarding) - boarding.and(0b0011_0011u) == (0b0001_0000).toUByte() -> context.getString(R.string.off_boarding) - boarding.and(0b0011_0011u) == (0b0001_0001).toUByte() -> context.getString(R.string.boarding) - else -> context.getString(R.string.on_demand) - } - } -} diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Event.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Event.kt new file mode 100644 index 0000000000000000000000000000000000000000..5e70e8f0e8435eec878d87e43e5edcbde64ba262 --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Event.kt @@ -0,0 +1,302 @@ +// SPDX-FileCopyrightText: Adam Evyčędo +// +// SPDX-License-Identifier: GPL-3.0-or-later + +package xyz.apiote.bimba.czwek.repo + +import android.content.Context +import android.text.format.DateUtils +import xyz.apiote.bimba.czwek.R +import xyz.apiote.bimba.czwek.api.AlertCauseV1 +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.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 +import xyz.apiote.bimba.czwek.units.TGM +import xyz.apiote.bimba.czwek.units.UnitSystem +import java.time.Instant +import java.time.ZoneId +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.time.temporal.ChronoUnit + + +class EventItem { + private constructor(d: Event?, a: List<Alert>) { + event = d + alert = a + } + + constructor(d: Event) : this(d, emptyList()) + constructor(a: List<Alert>) : this(null, a) + + val event: Event? + val alert: List<Alert> +} + +enum class AlertCause { + UNKNOWN, OTHER, TECHNICAL_PROBLEM, STRIKE, DEMONSTRATION, ACCIDENT, HOLIDAY, WEATHER, MAINTENANCE, + CONSTRUCTION, POLICE_ACTIVITY, MEDICAL_EMERGENCY; + + companion object { + fun of(type: AlertCauseV1): AlertCause { + return when (type) { + AlertCauseV1.UNKNOWN -> valueOf("UNKNOWN") + AlertCauseV1.OTHER -> valueOf("OTHER") + AlertCauseV1.TECHNICAL_PROBLEM -> valueOf("TECHNICAL_PROBLEM") + AlertCauseV1.STRIKE -> valueOf("STRIKE") + AlertCauseV1.DEMONSTRATION -> valueOf("DEMONSTRATION") + AlertCauseV1.ACCIDENT -> valueOf("ACCIDENT") + AlertCauseV1.HOLIDAY -> valueOf("HOLIDAY") + AlertCauseV1.WEATHER -> valueOf("WEATHER") + AlertCauseV1.MAINTENANCE -> valueOf("MAINTENANCE") + AlertCauseV1.CONSTRUCTION -> valueOf("CONSTRUCTION") + AlertCauseV1.POLICE_ACTIVITY -> valueOf("POLICE_ACTIVITY") + AlertCauseV1.MEDICAL_EMERGENCY -> valueOf("MEDICAL_EMERGENCY") + } + } + } +} + +enum class AlertEffect { + UNKNOWN, OTHER, NO_SERVICE, REDUCED_SERVICE, SIGNIFICANT_DELAYS, DETOUR, ADDITIONAL_SERVICE, + MODIFIED_SERVICE, STOP_MOVED, NONE, ACCESSIBILITY_ISSUE; + + companion object { + fun of(type: AlertEffectV1): AlertEffect { + return when (type) { + AlertEffectV1.UNKNOWN -> valueOf("UNKNOWN") + AlertEffectV1.OTHER -> valueOf("OTHER") + AlertEffectV1.NO_SERVICE -> valueOf("NO_SERVICE") + AlertEffectV1.REDUCED_SERVICE -> valueOf("REDUCED_SERVICE") + AlertEffectV1.SIGNIFICANT_DELAYS -> valueOf("SIGNIFICANT_DELAYS") + AlertEffectV1.DETOUR -> valueOf("DETOUR") + AlertEffectV1.ADDITIONAL_SERVICE -> valueOf("ADDITIONAL_SERVICE") + AlertEffectV1.MODIFIED_SERVICE -> valueOf("MODIFIED_SERVICE") + AlertEffectV1.STOP_MOVED -> valueOf("STOP_MOVED") + AlertEffectV1.NONE -> valueOf("NONE") + AlertEffectV1.ACCESSIBILITY_ISSUE -> valueOf("ACCESSIBILITY_ISSUE") + } + } + } +} + +data class Alert( + val header: String, + val description: String, + val url: String, + val cause: AlertCause, + val effect: AlertEffect +) { + constructor(a: AlertV1) : this( + a.header, + a.Description, + a.Url, + AlertCause.of(a.Cause), + AlertEffect.of(a.Effect) + ) +} + +data class StopEvents( + val events: List<Event>, + val stop: Stop, + val alerts: List<Alert> +) + +data class Event( + val id: String, + val arrivalTime: Time?, + val departureTime: Time?, + val status: ULong, + val isRealtime: Boolean, + val vehicle: Vehicle, + val boarding: UByte, + val alerts: List<Alert>, + val exact: Boolean, + val terminusArrival: Boolean // TODO origin, middle, terminus; if origin -> only departure, if terminus -> only arrival +) { + + constructor(d: DepartureV1) : this( + d.ID, + d.time, + d.time, + d.status, + d.isRealtime, + Vehicle(d.vehicle), + d.boarding, + emptyList(), + true, + false + ) + + constructor(d: DepartureV2) : this( + d.ID, + d.time, + d.time, + d.status, + d.isRealtime, + Vehicle(d.vehicle), + d.boarding, + emptyList(), + true, + false + ) + + constructor(d: DepartureV3) : this( + d.ID, + d.time, + d.time, + d.status.ordinal.toULong(), // TODO VehicleStatus + d.isRealtime, + Vehicle(d.vehicle), + d.boarding, + emptyList(), + true, + false + ) + + constructor(d: DepartureV4) : this( + d.ID, + d.time, + d.time, + d.status.ordinal.toULong(), // TODO VehicleStatus + d.isRealtime, + Vehicle(d.vehicle), + d.boarding, + d.alerts.map { Alert(it) }, + true, + false + ) + + constructor(d: DepartureV5) : this( + d.ID, + d.time, + 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 timeZone() = (arrivalTime ?: departureTime)!!.Zone + + fun filterTime() = (arrivalTime ?: departureTime)!! + + fun statusText( + context: Context?, + showAsTime: Boolean, + at: ZonedDateTime? = null + ): Pair<String?, String?> { + val now = at ?: Instant.now().atZone(ZoneId.systemDefault()) + return Pair( + statusText(context, showAsTime, now, arrivalTime, R.string.departure_arrived), + statusText(context, showAsTime, now, departureTime, R.string.departure_departed) + ) + } + + private fun statusText( + context: Context?, + showAsTime: Boolean, + now: ZonedDateTime, + time: Time?, + pastString: Int + ): String? { + val r = status.toUInt() + return time?.let { + ZonedDateTime.of( + now.year, + now.monthValue, + now.dayOfMonth, + it.Hour.toInt(), + it.Minute.toInt(), + it.Second.toInt(), + 0, + ZoneId.of( + it.Zone + ) + ) + .plus(it.DayOffset.toLong(), ChronoUnit.DAYS) + .let { + if (showAsTime) { + it.format(DateTimeFormatter.ofPattern("HH:mm")) + } else { + when { + // TODO why this condition + r == 0u || (it.isBefore(now) && r < 3u) -> if (context != null && UnitSystem.getSelected( + context + ) is TGM + ) { + val us = UnitSystem.getSelected(context) + us.toString( + context, + us.timeUnit(Second((it.toEpochSecond() - now.toEpochSecond()).toInt())) + ) + } else { + DateUtils.getRelativeTimeSpanString( + it.toEpochSecond() * 1000, + now.toEpochSecond() * 1000, + DateUtils.MINUTE_IN_MILLIS, + DateUtils.FORMAT_ABBREV_RELATIVE + ).toString() + } + + r == 1u -> context?.getString(R.string.departure_momentarily) ?: "momentarily" + r == 2u -> context?.getString(R.string.departure_now) ?: "now" + r == 3u -> context?.getString(pastString) ?: "passed" + else -> throw UnknownResourceVersionException("VehicleStatus/$r", 1u) + } + } + } + } + } + + fun departureTimeString(context: Context): String? = timeString(context, departureTime) + + fun arrivalTimeString(context: Context): String? = timeString(context, arrivalTime) + + private fun timeString(context: Context, time: Time?): String? { + return when { + time == null -> null + isRealtime -> context.getString( + R.string.at_time_realtime, + time.Hour.toInt(), + time.Minute.toInt(), + time.Second.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() + ) + } + + } + + fun boardingText(context: Context): String { + // todo [3.x] probably should take into account (on|off)-boarding only, on demand + return when { + boarding == (0b0000_0000).toUByte() -> context.getString(R.string.no_boarding) + boarding == (0b1111_1111).toUByte() -> "" // unknown + boarding.and(0b0011_0011u) == (0b0000_0001).toUByte() -> context.getString(R.string.on_boarding) + boarding.and(0b0011_0011u) == (0b0001_0000).toUByte() -> context.getString(R.string.off_boarding) + boarding.and(0b0011_0011u) == (0b0001_0001).toUByte() -> context.getString(R.string.boarding) + else -> context.getString(R.string.on_demand) + } + } +} diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Interfaces.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Interfaces.kt index a337b0178c144f066ffea44ebd3898c475d850c0..e612503b10f270a49961d1482475da55fb3f47db 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Interfaces.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Interfaces.kt @@ -36,7 +36,7 @@ stop: String, date: LocalDate?, context: Context, limit: Int? - ): StopDepartures? + ): StopEvents? suspend fun getLocatablesIn( context: Context, diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/OfflineRepository.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/OfflineRepository.kt index b11a5dfcccc9048e0390e0dfe9ad530e875a7668..309d6ec0f00248d543db51e92389dfddb1457a3d 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/OfflineRepository.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/OfflineRepository.kt @@ -200,7 +200,7 @@ stop: String, date: LocalDate?, context: Context, limit: Int? - ): StopDepartures? { + ): StopEvents? { TODO("Not yet implemented") } 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 89f7f8d5ccc84cde130f7c6a92ded75a16e30170..0b47623ff0b1f191b90a9e19f308f9a50878117f 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 @@ -114,7 +114,7 @@ stop: String, date: LocalDate?, context: Context, limit: Int? - ): StopDepartures? { + ): StopEvents? { return if (feedID == "transitous") { getTransitousDepartures(context, stop, date, limit) } else { @@ -137,28 +137,28 @@ } } else { when (val response = withContext(Dispatchers.IO) { DeparturesResponse.unmarshal(result.stream!!) }) { - is DeparturesResponseDev -> StopDepartures( - response.departures.map { Departure(it) }, + is DeparturesResponseDev -> StopEvents( + response.departures.map { Event(it) }, Stop(response.stop), response.alerts.map { Alert(it) }) - is DeparturesResponseV4 -> StopDepartures( - response.departures.map { Departure(it) }, + is DeparturesResponseV4 -> StopEvents( + response.departures.map { Event(it) }, Stop(response.stop), response.alerts.map { Alert(it) }) - is DeparturesResponseV3 -> StopDepartures( - response.departures.map { Departure(it) }, + is DeparturesResponseV3 -> StopEvents( + response.departures.map { Event(it) }, Stop(response.stop), response.alerts.map { Alert(it) }) - is DeparturesResponseV2 -> StopDepartures( - response.departures.map { Departure(it) }, + is DeparturesResponseV2 -> StopEvents( + response.departures.map { Event(it) }, Stop(response.stop), response.alerts.map { Alert(it) }) - is DeparturesResponseV1 -> StopDepartures( - response.departures.map { Departure(it) }, + is DeparturesResponseV1 -> StopEvents( + response.departures.map { Event(it) }, Stop(response.stop), response.alerts.map { Alert(it) }) diff --git a/app/src/main/res/drawable/radar.xml b/app/src/main/res/drawable/radar.xml index f68d13754fc956d4f9ac08166860576029d28b09..376de31d4cfec3e89591559016392ec6588e29ca 100644 --- a/app/src/main/res/drawable/radar.xml +++ b/app/src/main/res/drawable/radar.xml @@ -4,8 +4,15 @@ 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="M19.74,18.33C21.15,16.6 22,14.4 22,12c0,-5.52 -4.48,-10 -10,-10S2,6.48 2,12s4.48,10 10,10c2.4,0 4.6,-0.85 6.33,-2.26c0.27,-0.22 0.53,-0.46 0.78,-0.71c0.03,-0.03 0.05,-0.06 0.07,-0.08C19.38,18.75 19.57,18.54 19.74,18.33zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8c0,1.85 -0.63,3.54 -1.69,4.9l-1.43,-1.43c0.69,-0.98 1.1,-2.17 1.1,-3.46c0,-3.31 -2.69,-6 -6,-6s-6,2.69 -6,6s2.69,6 6,6c1.3,0 2.51,-0.42 3.49,-1.13l1.42,1.42C15.54,19.37 13.85,20 12,20zM13.92,12.51c0.17,-0.66 0.02,-1.38 -0.49,-1.9l-0.02,-0.02c-0.77,-0.77 -2,-0.78 -2.78,-0.04c-0.01,0.01 -0.03,0.02 -0.05,0.04c-0.78,0.78 -0.78,2.05 0,2.83l0.02,0.02c0.52,0.51 1.25,0.67 1.91,0.49l1.51,1.51c-0.6,0.36 -1.29,0.58 -2.04,0.58c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4s4,1.79 4,4c0,0.73 -0.21,1.41 -0.56,2L13.92,12.51z" /> +<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="M15.44,0.59l-3.18,3.18c-0.78,0.78 -0.78,2.05 0,2.83l1.24,1.24l-0.71,0.71L11.55,7.3c-0.78,-0.78 -2.05,-0.78 -2.83,0L7.3,8.72c-0.78,0.78 -0.78,2.05 0,2.83l1.24,1.24l-0.71,0.71L6.6,12.25c-0.78,-0.78 -2.05,-0.78 -2.83,0l-3.18,3.18c-0.78,0.78 -0.78,2.05 0,2.83l3.54,3.54c0.78,0.78 2.05,0.78 2.83,0l3.18,-3.18c0.78,-0.78 0.78,-2.05 0,-2.83l-1.24,-1.24l0.71,-0.71l1.24,1.24c0.78,0.78 2.05,0.78 2.83,0l1.41,-1.41c0.78,-0.78 0.78,-2.05 0,-2.83L13.84,9.6l0.71,-0.71l1.24,1.24c0.78,0.78 2.05,0.78 2.83,0l3.18,-3.18c0.78,-0.78 0.78,-2.05 0,-2.83l-3.54,-3.54C17.48,-0.2 16.22,-0.2 15.44,0.59zM6.6,19.32l-1.06,1.06L2,16.85l1.06,-1.06L6.6,19.32zM8.72,17.2l-1.06,1.06l-3.54,-3.54l1.06,-1.06L8.72,17.2zM18.26,7.66L17.2,8.72l-3.54,-3.54l1.06,-1.06L18.26,7.66zM20.38,5.54L19.32,6.6l-3.54,-3.54L16.85,2L20.38,5.54zM14,21l0,2c4.97,0 9,-4.03 9,-9l-2,0C21,17.87 17.87,21 14,21zM14,17l0,2c2.76,0 5,-2.24 5,-5l-2,0C17,15.66 15.66,17 14,17z" /> + </vector> diff --git a/app/src/main/res/layout/departure.xml b/app/src/main/res/layout/departure.xml index b2514262349aef0d448fed775a6116b4042ece6d..c3d8f14918808281ed2d6ce28a9ac3855f866213 100644 --- a/app/src/main/res/layout/departure.xml +++ b/app/src/main/res/layout/departure.xml @@ -7,63 +7,100 @@ SPDX-License-Identifier: GPL-3.0-or-later --> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tool="http://schemas.android.com/tools" - android:id="@+id/departure" - android:layout_width="match_parent" - android:layout_height="wrap_content"> + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tool="http://schemas.android.com/tools" + android:id="@+id/departure" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <ImageView + android:id="@+id/line_icon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_marginStart="8dp" + app:layout_constraintBottom_toBottomOf="@+id/departure_line" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="@+id/departure_line" + tool:ignore="ContentDescription" + tool:srcCompat="@drawable/bus_black" /> + + <com.google.android.material.textview.MaterialTextView + android:id="@+id/arrival_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginEnd="8dp" + android:textAppearance="@style/TextAppearance.Material3.LabelSmall" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + tool:text="approx. arr." /> + + <com.google.android.material.textview.MaterialTextView + android:id="@+id/arrival_time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/arrival_status" + tool:text="1hr" /> - <ImageView - android:id="@+id/line_icon" - android:layout_width="24dp" - android:layout_height="24dp" - android:layout_marginStart="8dp" - app:layout_constraintBottom_toTopOf="@+id/departure_headsign" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="@+id/departure_time" - tool:srcCompat="@drawable/bus_black" - tool:ignore="ContentDescription" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/departure_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginEnd="8dp" + android:textAppearance="@style/TextAppearance.Material3.LabelSmall" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/arrival_time" + tool:text="approx. dep." /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/departure_time" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:layout_marginEnd="8dp" - android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toTopOf="parent" - tool:text="1hr" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/departure_time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:layout_marginBottom="8dp" + android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/departure_status" + tool:text="1hr" /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/departure_line" - 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" - app:layout_constraintEnd_toStartOf="@id/departure_time" - tool:text="Circle" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/departure_line" + 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_constraintEnd_toStartOf="@id/arrival_time" + app:layout_constraintHorizontal_bias="1.0" + app:layout_constraintStart_toEndOf="@+id/line_icon" + app:layout_constraintTop_toTopOf="parent" + tool:text="Circle" /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/departure_headsign" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.Material3.BodySmall" - app:layout_constraintStart_toStartOf="@+id/departure_line" - app:layout_constraintTop_toBottomOf="@+id/departure_line" - tool:text="» Tower Hill" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/departure_headsign" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="@style/TextAppearance.Material3.BodySmall" + 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" /> + <ImageView + android:id="@+id/event_status" + android:layout_width="15dp" + android:layout_height="11dp" + android:layout_marginStart="8dp" + android:layout_marginBottom="8dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/departure_headsign" + app:layout_constraintVertical_bias="0.0" + tool:ignore="ContentDescription" + tool:srcCompat="@drawable/radar" /> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/departure_bottom_sheet.xml b/app/src/main/res/layout/departure_bottom_sheet.xml index 3b6e92fa314f2d9967ae05c9200666b9989f8bbb..f2bb7dc23101df9ee440b0a8997d2ebbfbe753ce 100644 --- a/app/src/main/res/layout/departure_bottom_sheet.xml +++ b/app/src/main/res/layout/departure_bottom_sheet.xml @@ -7,282 +7,316 @@ SPDX-License-Identifier: GPL-3.0-or-later --> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tool="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingBottom="16dp"> + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tool="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingBottom="16dp"> - <com.google.android.material.bottomsheet.BottomSheetDragHandleView - android:id="@+id/drag_handle" - android:layout_width="match_parent" - android:layout_height="wrap_content" - app:layout_constraintTop_toTopOf="parent" /> + <com.google.android.material.bottomsheet.BottomSheetDragHandleView + android:id="@+id/drag_handle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + app:layout_constraintTop_toTopOf="parent" /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/time" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="0dp" - android:textAppearance="@style/TextAppearance.Material3.DisplaySmall" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/drag_handle" - tool:text="at 12:10:30" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/arrival_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="0dp" + android:textAppearance="@style/TextAppearance.Material3.BodySmall" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/drag_handle" + tool:text="approx. arr." /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/local_time" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - app:layout_constraintTop_toBottomOf="@+id/time" - app:layout_constraintEnd_toEndOf="@+id/time" - android:text="@string/local_time" - android:visibility="gone" - app:layout_constraintStart_toStartOf="@+id/time" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/arrival_time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="0dp" + android:textAppearance="@style/TextAppearance.Material3.DisplaySmall" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/arrival_status" + tool:text="at 12:10:30" /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/offset" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginStart="4dp" - android:textAppearance="@style/TextAppearance.Material3.BodyLarge" - android:visibility="gone" - app:layout_constraintBaseline_toBaselineOf="@+id/time" - app:layout_constraintStart_toEndOf="@+id/time" - tool:text="(+2 min)" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/departure_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:visibility="gone" + android:textAppearance="@style/TextAppearance.Material3.BodySmall" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/arrival_time" + tool:text="approx. dep." /> - <ImageView - android:id="@+id/rt_icon" - android:layout_width="24dp" - android:layout_height="24dp" - android:layout_marginStart="16dp" - android:contentDescription="@string/realtime_content_description" - app:layout_constraintBottom_toBottomOf="@+id/time" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="@+id/time" - app:srcCompat="@drawable/radar" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/departure_time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="0dp" + android:visibility="gone" + android:textAppearance="@style/TextAppearance.Material3.DisplaySmall" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/departure_status" + tool:text="at 12:10:30" /> - <ImageView - android:id="@+id/wheelchair_icon" - android:layout_width="24dp" - android:layout_height="24dp" - android:layout_marginStart="8dp" - android:contentDescription="@string/wheelchair_content_description" - app:layout_constraintStart_toEndOf="@id/rt_icon" - app:layout_constraintTop_toTopOf="@+id/rt_icon" - app:srcCompat="@drawable/wheelchair" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/local_time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/local_time" + android:visibility="gone" + app:layout_constraintEnd_toEndOf="@+id/departure_time" + app:layout_constraintStart_toStartOf="@+id/departure_time" + app:layout_constraintTop_toBottomOf="@+id/departure_time" /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/line" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="8dp" - android:textAlignment="center" - android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/local_time" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/offset" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="4dp" + android:textAppearance="@style/TextAppearance.Material3.BodyLarge" + android:visibility="gone" + app:layout_constraintBaseline_toBaselineOf="@+id/arrival_time" + app:layout_constraintStart_toEndOf="@+id/arrival_time" + tool:text="(+2 min)" /> - <androidx.constraintlayout.helper.widget.Flow - android:id="@+id/info" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginStart="48dp" - android:layout_marginTop="48dp" - android:layout_marginEnd="48dp" - app:constraint_referenced_ids="boarding,speed,congestion,occupancy" - app:flow_horizontalGap="4dp" - app:flow_horizontalStyle="spread_inside" - app:flow_verticalGap="4dp" - app:flow_wrapMode="chain" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/line" /> + <ImageView + android:id="@+id/rt_icon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_marginStart="16dp" + android:contentDescription="@string/realtime_content_description" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/drag_handle" + app:srcCompat="@drawable/radar" /> - <LinearLayout - android:id="@+id/boarding" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="center_vertical"> + <ImageView + android:id="@+id/wheelchair_icon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_marginStart="8dp" + android:contentDescription="@string/wheelchair_content_description" + app:layout_constraintStart_toEndOf="@id/rt_icon" + app:layout_constraintTop_toTopOf="@+id/rt_icon" + app:srcCompat="@drawable/wheelchair" /> - <ImageView - android:id="@+id/boarding_icon" - android:layout_width="16dp" - android:layout_height="16dp" - android:layout_marginEnd="8dp" - android:importantForAccessibility="no" - app:srcCompat="@drawable/transfer" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/line" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginTop="8dp" + android:layout_marginEnd="8dp" + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/local_time" /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/boarding_text" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="8dp" - android:textAppearance="@style/TextAppearance.Material3.BodyLarge" - tool:text="on demand" /> - </LinearLayout> + <androidx.constraintlayout.helper.widget.Flow + android:id="@+id/info" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="48dp" + android:layout_marginTop="48dp" + android:layout_marginEnd="48dp" + app:constraint_referenced_ids="boarding,speed,congestion,occupancy" + app:flow_horizontalGap="4dp" + app:flow_horizontalStyle="spread_inside" + app:flow_verticalGap="4dp" + app:flow_wrapMode="chain" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/line" /> - <LinearLayout - android:id="@+id/speed" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="center_vertical"> + <LinearLayout + android:id="@+id/boarding" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="center_vertical"> - <ImageView - android:id="@+id/speed_icon" - android:layout_width="16dp" - android:layout_height="16dp" - android:layout_marginEnd="8dp" - android:importantForAccessibility="no" - app:srcCompat="@drawable/speed" /> + <ImageView + android:id="@+id/boarding_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_marginEnd="8dp" + android:importantForAccessibility="no" + app:srcCompat="@drawable/transfer" /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/speed_text" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="8dp" - android:textAppearance="@style/TextAppearance.Material3.BodyLarge" - tool:text="10 Vl" /> - </LinearLayout> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/boarding_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:textAppearance="@style/TextAppearance.Material3.BodyLarge" + tool:text="on demand" /> + </LinearLayout> - <LinearLayout - android:id="@+id/congestion" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="center_vertical"> + <LinearLayout + android:id="@+id/speed" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="center_vertical"> + + <ImageView + android:id="@+id/speed_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_marginEnd="8dp" + android:importantForAccessibility="no" + app:srcCompat="@drawable/speed" /> - <ImageView - android:id="@+id/congestion_icon" - android:layout_width="16dp" - android:layout_height="16dp" - android:layout_marginEnd="8dp" - android:importantForAccessibility="no" - app:srcCompat="@drawable/traffic" /> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/speed_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:textAppearance="@style/TextAppearance.Material3.BodyLarge" + tool:text="10 Vl" /> + </LinearLayout> + + <LinearLayout + android:id="@+id/congestion" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="center_vertical"> + + <ImageView + android:id="@+id/congestion_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_marginEnd="8dp" + android:importantForAccessibility="no" + app:srcCompat="@drawable/traffic" /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/congestion_text" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="8dp" - android:textAppearance="@style/TextAppearance.Material3.BodyLarge" - tool:text="smooth traffic" /> - </LinearLayout> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/congestion_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:textAppearance="@style/TextAppearance.Material3.BodyLarge" + tool:text="smooth traffic" /> + </LinearLayout> - <LinearLayout - android:id="@+id/occupancy" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="center_vertical"> + <LinearLayout + android:id="@+id/occupancy" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="center_vertical"> - <ImageView - android:id="@+id/occupancy_icon" - android:layout_width="16dp" - android:layout_height="16dp" - android:layout_marginEnd="8dp" - android:importantForAccessibility="no" - app:srcCompat="@drawable/crowd" /> + <ImageView + android:id="@+id/occupancy_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_marginEnd="8dp" + android:importantForAccessibility="no" + app:srcCompat="@drawable/crowd" /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/occupancy_text" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="8dp" - android:textAppearance="@style/TextAppearance.Material3.BodyLarge" - tool:text="empty vehicle" /> - </LinearLayout> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/occupancy_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:textAppearance="@style/TextAppearance.Material3.BodyLarge" + tool:text="empty vehicle" /> + </LinearLayout> - <androidx.constraintlayout.helper.widget.Flow - android:id="@+id/capabilities" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="16dp" - android:layout_marginEnd="8dp" - app:constraint_referenced_ids="ac,bike,voice,ticket,usb" - app:flow_horizontalGap="4dp" - app:flow_horizontalStyle="packed" - app:flow_verticalGap="4dp" - app:flow_wrapMode="chain" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/info" /> + <androidx.constraintlayout.helper.widget.Flow + android:id="@+id/capabilities" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginTop="16dp" + android:layout_marginEnd="8dp" + app:constraint_referenced_ids="ac,bike,voice,ticket,usb" + app:flow_horizontalGap="4dp" + app:flow_horizontalStyle="packed" + app:flow_verticalGap="4dp" + app:flow_wrapMode="chain" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/info" /> - <ImageView - android:id="@+id/ac" - android:layout_width="24dp" - android:layout_height="24dp" - android:contentDescription="@string/air_condition_content_description" - app:srcCompat="@drawable/ac" - tool:ignore="MissingConstraints" /> + <ImageView + android:id="@+id/ac" + android:layout_width="24dp" + android:layout_height="24dp" + android:contentDescription="@string/air_condition_content_description" + app:srcCompat="@drawable/ac" + tool:ignore="MissingConstraints" /> - <ImageView - android:id="@+id/bike" - android:layout_width="24dp" - android:layout_height="24dp" - android:contentDescription="@string/bicycles_allowed_content_description" - app:srcCompat="@drawable/bike" - tool:ignore="MissingConstraints" /> + <ImageView + android:id="@+id/bike" + android:layout_width="24dp" + android:layout_height="24dp" + android:contentDescription="@string/bicycles_allowed_content_description" + app:srcCompat="@drawable/bike" + tool:ignore="MissingConstraints" /> - <ImageView - android:id="@+id/voice" - android:layout_width="24dp" - android:layout_height="24dp" - android:contentDescription="@string/voice_announcements_content_description" - app:srcCompat="@drawable/voice" - tool:ignore="MissingConstraints" /> + <ImageView + android:id="@+id/voice" + android:layout_width="24dp" + android:layout_height="24dp" + android:contentDescription="@string/voice_announcements_content_description" + app:srcCompat="@drawable/voice" + tool:ignore="MissingConstraints" /> - <ImageView - android:id="@+id/ticket" - android:layout_width="24dp" - android:layout_height="24dp" - android:contentDescription="@string/tickets_sold_content_description" - app:srcCompat="@drawable/ticket" - tool:ignore="MissingConstraints" /> + <ImageView + android:id="@+id/ticket" + android:layout_width="24dp" + android:layout_height="24dp" + android:contentDescription="@string/tickets_sold_content_description" + app:srcCompat="@drawable/ticket" + tool:ignore="MissingConstraints" /> - <ImageView - android:id="@+id/usb" - android:layout_width="24dp" - android:layout_height="24dp" - android:contentDescription="@string/usb_charging_content_description" - app:srcCompat="@drawable/usb" - tool:ignore="MissingConstraints" /> + <ImageView + android:id="@+id/usb" + android:layout_width="24dp" + android:layout_height="24dp" + android:contentDescription="@string/usb_charging_content_description" + app:srcCompat="@drawable/usb" + tool:ignore="MissingConstraints" /> - <LinearLayout - android:layout_marginTop="8dp" - android:id="@+id/alerts" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="center_vertical" - android:visibility="gone" - android:background="@color/safety" - app:layout_constraintTop_toBottomOf="@+id/capabilities"> + <LinearLayout + android:id="@+id/alerts" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:background="@color/safety" + android:gravity="center_vertical" + android:visibility="gone" + app:layout_constraintTop_toBottomOf="@+id/capabilities"> - <ImageView - android:layout_marginStart="8dp" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - app:tint="@color/black" - android:importantForAccessibility="no" - android:src="@drawable/warning" /> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:importantForAccessibility="no" + android:src="@drawable/warning" + app:tint="@color/black" /> - <com.google.android.material.textview.MaterialTextView - android:id="@+id/alerts_text" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_margin="8dp" - android:padding="8dp" - android:textColor="@color/black" - tool:text="Severe stops on Metropolitan line towards Tower Hill through Victoria" /> - </LinearLayout> + <com.google.android.material.textview.MaterialTextView + android:id="@+id/alerts_text" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="8dp" + android:padding="8dp" + android:textColor="@color/black" + tool:text="Severe stops on Metropolitan line towards Tower Hill through Victoria" /> + </LinearLayout> - <org.osmdroid.views.MapView - android:id="@+id/map" - android:layout_width="match_parent" - android:layout_height="250dp" - android:layout_margin="16dp" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/alerts" /> + <org.osmdroid.views.MapView + android:id="@+id/map" + android:layout_width="match_parent" + android:layout_height="250dp" + android:layout_margin="16dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/alerts" /> </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/layout/favourite.xml b/app/src/main/res/layout/favourite.xml index 7d47ac03dc672895ee185d4c471ffb19cf4847b7..c4175c5cfe973887027f17ba67804556823382f4 100644 --- a/app/src/main/res/layout/favourite.xml +++ b/app/src/main/res/layout/favourite.xml @@ -7,10 +7,10 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tool="http://schemas.android.com/tools" android:id="@+id/favourite" - android:layout_marginTop="8dp" - android:layout_marginBottom="8dp" android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginBottom="8dp"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" @@ -45,18 +45,60 @@ android:layout_height="24dp" android:layout_marginStart="8dp" app:layout_constraintBottom_toTopOf="@+id/departure_headsign" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="@+id/departure_time" + app:layout_constraintTop_toTopOf="@+id/departure_line" tool:ignore="ContentDescription" tool:srcCompat="@drawable/bus_black" /> <com.google.android.material.textview.MaterialTextView - android:id="@+id/departure_time" + android:id="@+id/arrival_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginEnd="8dp" + android:textAppearance="@style/TextAppearance.Material3.LabelSmall" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + tool:text="approx. arr." /> + + <com.google.android.material.textview.MaterialTextView + android:id="@+id/arrival_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/arrival_status" + tool:text="1hr" /> + + <com.google.android.material.textview.MaterialTextView + android:id="@+id/arrival_full_time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="4dp" + android:textAppearance="@style/TextAppearance.Material3.LabelSmall" + app:layout_constraintEnd_toEndOf="@+id/arrival_time" + app:layout_constraintTop_toBottomOf="@+id/arrival_time" + tool:text="18:55" /> + + <com.google.android.material.textview.MaterialTextView + android:id="@+id/departure_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginEnd="8dp" + android:textAppearance="@style/TextAppearance.Material3.LabelSmall" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/departure_line" + tool:text="approx. dep." /> + + <com.google.android.material.textview.MaterialTextView + android:id="@+id/departure_time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/departure_status" tool:text="1hr" /> <com.google.android.material.textview.MaterialTextView diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f0881e76ecbc33476956161aa61f7919fde2a3d0..d7eabb6448290335cfad6b1b52b8943562ede311 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -149,9 +149,7 @@ Server <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="schedule_content_description">departure time is 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> @@ -288,4 +286,10 @@link to email <string name="transitous_description">A community-run provider-neutral international public transport routing service. Coverage is available at https://transitous.org/sources/</string> <string name="transitous_attribution">Transitous (https://transitous.org) API provided by Spline (https://routing.spline.de). Localities (https://github.com/public-transport/transitous/tree/main/feeds) maintained by the community.</string> <string name="local_time">local time</string> + <string name="departure_arrived">arrived</string> + <string name="arrival_approximate">approx. arr.</string> + <string name="arrival">arrival</string> + <string name="departure_approximate">approx. dep.</string> + <string name="departure">departure</string> + <string name="approximately">approximately</string> </resources> diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 042048b10e8ca72c5956032013ac943358cfae06..1f990cc3b25e064ea38ef5e14bc97f87aa2297e5 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -58,8 +58,8 @@- 9sp
</style> <style name="Theme.Bimba.Splash" parent="Theme.SplashScreen"> - <item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item> - <item name="windowSplashScreenIconBackgroundColor">@color/ic_launcher_background</item> + <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item> + <item name="windowSplashScreenBackground">?attr/colorSurface</item> <item name="postSplashScreenTheme">@style/Theme.Bimba</item> </style> diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index e39bfc51ee91e735e1e5a29982850c5b76cfddd5..bdc076567a58b017c5a152746e2ba04f6e14a2b6 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -147,9 +147,7 @@Server <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="schedule_content_description">departure time is 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> @@ -286,4 +284,10 @@link to email <string name="transitous_description">A community-run provider-neutral international public transport routing service. Coverage is available at https://transitous.org/sources/</string> <string name="transitous_attribution">Transitous (https://transitous.org) API provided by Spline (https://routing.spline.de). Localities (https://github.com/public-transport/transitous/tree/main/feeds) maintained by the community.</string> <string name="local_time">local time</string> + <string name="departure_arrived">arrived</string> + <string name="arrival_approximate">approx. arr.</string> + <string name="arrival">arrival</string> + <string name="departure_approximate">approx. dep.</string> + <string name="departure">departure</string> + <string name="approximately">approximately</string> </resources> diff --git a/app/src/main/res/values-en-rUS/strings.xml b/app/src/main/res/values-en-rUS/strings.xml index e41b22e601cc5d006112aa47cb3f0a9ea341921a..075852ab7b5dd2b4fc0fca4e326a543a1ea2f949 100644 --- a/app/src/main/res/values-en-rUS/strings.xml +++ b/app/src/main/res/values-en-rUS/strings.xml @@ -103,8 +103,7 @@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> - <string name="exact_content_description">departure time is exact from schedule</string> - <string name="inexact_content_description">departure time is approximate</string> + <string name="schedule_content_description">departure time is 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> @@ -283,4 +282,10 @@No email app installed <string name="transitous_description">A community-run provider-neutral international public transport routing service. Coverage is available at https://transitous.org/sources/</string> <string name="transitous_attribution">Transitous (https://transitous.org) API provided by Spline (https://routing.spline.de). Localities (https://github.com/public-transport/transitous/tree/main/feeds) maintained by the community.</string> <string name="local_time">local time</string> + <string name="departure_arrived">arrived</string> + <string name="arrival_approximate">approx. arr.</string> + <string name="arrival">arrival</string> + <string name="departure_approximate">approx. dep.</string> + <string name="departure">departure</string> + <string name="approximately">approximately</string> </resources> \ No newline at end of file diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..0480a5fed0a434e65ffaebf0d90a926db77025fe --- /dev/null +++ b/app/src/main/res/values-et/strings.xml @@ -0,0 +1,278 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="error_403">Sinu sisestatud ligipääsutunnus pole õige</string> + <string name="error_404">Otsitavat ei leidu</string> + <string name="error_50x">Serveris tekkis viga. Palun proovi hiljem uuesti</string> + <string name="error_unknown">Tekkis tundmatu viga</string> + <string name="error_connecting">Ühenduse loomisel serveriga tekkis viga. Palun proovi hiljem uuesti</string> + <string name="no_departures">Väljumisi pole</string> + <string name="error_gps">Praegust asukohta ei õnnestu tuvastada</string> + <string name="vehicle_headsign"><annotation decoration="apply"><annotation arg="0">%1$s</annotation></annotation> » <annotation arg="1">%2$s</annotation></string> + <plurals name="distance_in_m_cd"> + <item quantity="one">%1$d meeter</item> + <item quantity="other">%1$d meetrit</item> + </plurals> + <string name="distance_in_two_units_cd">%1$s ja %2$s</string> + <plurals name="distance_in_yd_cd"> + <item quantity="one">%1$d jard</item> + <item quantity="other">%1$d jardi</item> + </plurals> + <plurals name="distance_in_ft_cd"> + <item quantity="one">%1$d jalg</item> + <item quantity="other">%1$d jalga</item> + </plurals> + <string name="distance_in_ft">%1$s jlg</string> + <plurals name="time_in_s_cd"> + <item quantity="one">%1$d sekund</item> + <item quantity="other">%1$d sekundit</item> + </plurals> + <plurals name="time_in_2tm_12_cd"> + <item quantity="one">%1$s dunatim</item> + <item quantity="other">%1$s dunatimmi</item> + </plurals> + <string name="speed_in_m_per_s">%1$s m/s</string> + <string name="time_in_tm">%1$s %2$sTm</string> + <string name="speed_in_km_per_h">%1$s km/h</string> + <plurals name="speed_in_vl_cd"> + <item quantity="one">%1$d vlos</item> + <item quantity="other">%1$d vlos</item> + </plurals> + <string name="speed_in_mi_per_h">%1$s mt</string> + <string name="speed_in_vl">%1$s Vl</string> + <plurals name="speed_in_m_per_s_cd"> + <item quantity="one">%1$d meeter sekundis</item> + <item quantity="other">%1$d meetrit sekundis</item> + </plurals> + <plurals name="speed_in_km_per_h_cd"> + <item quantity="one">%1$d kilomeeter tunnis</item> + <item quantity="other">%1$d kilomeetrit tunnis</item> + </plurals> + <plurals name="speed_in_mi_per_h_cd"> + <item quantity="one">%1$d miili tunnis</item> + <item quantity="other">%1$d miili tunnis</item> + </plurals> + <plurals name="speed_in_vl_12_cd"> + <item quantity="one">%1$s vlos</item> + <item quantity="other">%1$s vlos</item> + </plurals> + <string name="congestion_stop_and_go">liigub ja peatub</string> + <string name="no_email_app">Nutiseadmes ei leidu ühtegi e-postirakendust</string> + <string name="occupancy_standing_only">vaid seisukohad</string> + <string name="congestion_jams">suur ummik</string> + <string name="occupancy_many_seats">palju vabu kohti</string> + <string name="occupancy_full">täiesti täis</string> + <string name="occupancy_few_seats">mõned vabad kohad</string> + <string name="about_time">umbes %1$02d:%2$02d</string> + <string name="departure_momentarily">just nüüd</string> + <string name="off_boarding">mahatulek</string> + <string name="line_headsign">» %1$s</string> + <string name="line_headsigns">%1$s «» %2$s</string> + <string name="results_for">Otsingutulemused: „%1$s“</string> + <string name="bimba_server_address_hint">Server</string> + <string name="server_rate_limited_question">See server kasutab päringumahu piiranguid ning ligipääsutunnus on sisestamata. Kas sa soovid jätkata?</string> + <string name="server_private_question">See on privaatne server ning ligipääsutunnus on sisestamata</string> + <string name="realtime_content_description">väljumine on reaalajas</string> + <string name="voice_announcements_content_description">kasutusel on häälteated</string> + <string name="tickets_sold_content_description">transpordivahendis müüakse sõidupileteid</string> + <string name="usb_charging_content_description">USB-põhised laadimispordid on olemas</string> + <string name="open_in_maps_app">Ava kaardirakenduses</string> + <string name="onboarding_advanced">Keerukamalt</string> + <string name="seatbelts_everyone">Palun kinnitage turvavööd!</string> + <string name="onboarding_simple">Lihtsalt</string> + <string name="error">Viga</string> + <string name="cancel">Katkesta</string> + <string name="rate_limit">Päringute piir</string> + <string name="title_servers">Serverid</string> + <string name="title_cities">Piirkonnad</string> + <string name="app_name">Bimba</string> + <string name="title_home">Avaleht</string> + <string name="title_map">Kaart</string> + <string name="title_journey">Reis</string> + <string name="home_fab_description">GPSi ikoon</string> + <string name="search_placeholder">peatus, liin või OLC kood</string> + <string name="save">Salvesta</string> + <string name="error_401">Selle serveri kasutamiseks on vajalik ligipääsutunnus</string> + <string name="error_429">Päringud on liiga sagedased. Palun proovi hiljem uuesti</string> + <string name="error_offline">Sa poel võrgus. Palun loo nutiseadmes võrguühendus</string> + <string name="waiting_position">Ootame asukoha tuvastamist</string> + <string name="distance_in_m">%1$s m</string> + <string name="distance_in_km">%1$s km</string> + <plurals name="distance_in_km_cd"> + <item quantity="one">%1$d kilomeeter</item> + <item quantity="other">%1$d kilomeetrit</item> + </plurals> + <string name="distance_in_yd">%1$s jd</string> + <string name="distance_in_mi">%1$s mi</string> + <plurals name="distance_in_mi_cd"> + <item quantity="one">%1$d miil</item> + <item quantity="other">%1$d miili</item> + </plurals> + <string name="distance_in_gf">%1$s %2$sGf</string> + <plurals name="distance_in_gf_cd"> + <item quantity="one">%1$d grafut</item> + <item quantity="other">%1$d grafutit</item> + </plurals> + <plurals name="distance_in_3gf_12_cd"> + <item quantity="one">%1$s trinagrafut</item> + <item quantity="other">%1$s trinagrafutit</item> + </plurals> + <plurals name="distance_in_gf_12_cd"> + <item quantity="one">%1$s grafut</item> + <item quantity="other">%1$s grafutit</item> + </plurals> + <string name="time_in_s">%1$s sek</string> + <string name="time_in_tm_past">%1$s %2$sTm tagasi</string> + <plurals name="time_in_tm_cd"> + <item quantity="one">%1$d tim</item> + <item quantity="other">%1$d timmi</item> + </plurals> + <plurals name="time_in_4tm_12_cd"> + <item quantity="one">%1$s kvadratim</item> + <item quantity="other">%1$s kvadratimmi</item> + </plurals> + <string name="congestion_unknown">teadmata</string> + <string name="congestion_smooth">sujuv</string> + <string name="congestion_congestion">väike ummik</string> + <string name="occupancy_unknown">teadmata</string> + <string name="occupancy_empty">tühi</string> + <string name="occupancy_crowded">peaaegu täis</string> + <string name="occupancy_wont_let">uusi reisijaid ei peale võeta</string> + <string name="no_map_app">Nutiseadmes ei leidu ühtegi kaardirakendust</string> + <string name="departure_headsign_content_description">%1$s suunas</string> + <string name="departure_departed">väljunud</string> + <string name="departure_now">nüüd</string> + <string name="at_time">kell %1$02d:%2$02d</string> + <string name="at_time_realtime">kell %1$02d:%2$02d:%3$02d</string> + <string name="on_demand">nõudepeatus</string> + <string name="no_boarding">pealeminekut pole</string> + <string name="on_boarding">pealeminek</string> + <string name="boarding">võid peale minna</string> + <string name="line_headsign_content_description">suunaga %1$s</string> + <string name="line_headsigns_content_description">%1$s ja %2$s vahel</string> + <string name="stops_nearby">Peatub läheduses</string> + <string name="bimba_server_token_hint">Ligipääsutunnus</string> + <string name="wheelchair_content_description">sõidukisse pääseb ratastooliga</string> + <string name="air_condition_content_description">kliimaseade</string> + <string name="show_departures">Näita väljumisi</string> + <string name="stop_content_description">peatus</string> + <string name="onboarding_question">Kuidas sa soovid alustada?</string> + <string name="onboarding_simple_action">vali piirkonnad</string> + <string name="onboarding_advanced_action">vali server</string> + <string name="last_update">Viimane uuendus: %1$s</string> + <string name="title_feeds">Sõiduplaanid</string> + <string name="error_url">Sisestatud võrguaadress on vigane</string> + <string name="error_traffic_spec">Serveri verifitseerimine ei õnnestu</string> + <string name="stops_near_code">Peatub %1$s lähedal</string> + <string name="stop_stub_on_demand_in_zone">Nõudepeatus tsoonis %1$s</string> + <string name="stop_stub_on_demand">Nõudepeatus</string> + <string name="stop_stub_in_zone">Peatus tsoonis %1$s</string> + <string name="vehicle_headsign_content_description">%1$s suunaga %2$s</string> + <string name="departure_headsign">» %1$s</string> + <string name="title_activity_results">Tulemused</string> + <string name="continue_">Jätka</string> + <string name="error_400">Rakendus tegi vigase päringu</string> + <string name="bicycles_allowed_content_description">jalgrattaid võib kaasa võtta</string> + <string name="choose_server">Vali serveri variant</string> + <string name="ok">Sobib</string> + <string name="no_location_access">Puudub ligipääs asukohale</string> + <string name="no_location_message">Õigus tuvastada asukohta on vajalik lähimate peatuste leidmiseks ja praeguse asukoha näitamiseks kaardil. Kõik muud funktsionaalsused toimivad ka ilma asukohta teadmata. Sa võid süsteemi seadistustest alati asukoha kasutamise õiguse sisse või välja lülitada - just nii nagu sulle oluline on.</string> + <string name="app_description">Avatud lähtekoodil põhinev kaaslane reisijatele - sõiduplaan sinu taskus.</string> + <string name="code_button_description">lähtekoodi link</string> + <string name="use_online_feed">Kasuta veebipõhist andmevoogu</string> + <string name="current_timetable_validity">Praeguse sõiduplaani kehtivus: %1$s kuni %2$s</string> + <string name="filter_localities">filtreeri piirkondi</string> + <string name="title_select_line">Vali liin</string> + <string name="more">Veel</string> + <string name="units_locale_based">Lokaadikohased</string> + <string name="units_imperial">Inglise süsteemi mõõtühikud (UK)</string> + <string name="units_tgm12">TGM (kaheteistkümnendsüsteemis)</string> + <string name="units_tgm10">TGM (kümnendsüsteemis)</string> + <string name="error_geocoding">Linna ei leidu</string> + <string name="cities_channel_name">Linnade uuendamise kanal</string> + <string name="cities_channel_description">Teavitus, mis näitab geokodeerimiseks vajalike andmete uuenduse edenemist</string> + <string name="updating_geocoding_data">Uuendame geokodeerimise andmeid</string> + <string name="zero">null</string> + <string name="one">üks</string> + <string name="two">kaks</string> + <string name="three">kolm</string> + <string name="four">neli</string> + <string name="five">viis</string> + <string name="send">Saada</string> + <string name="discard">Loobu</string> + <string name="send_with_comment">Saada kommentaariga</string> + <string name="local_time">kohalik aeg</string> + <string name="title_about">Rakenduse teave</string> + <string name="translation_button_description">rakenduse tõlkimise liidese link</string> + <string name="information_may_be_outdated">Informatsioon võib olla aegunud</string> + <string name="mastodon_button_description">Mastodoni link</string> + <string name="website_button_description">veebisaidi link</string> + <string name="error_406">Rakenduse versioon ei ühildu serveriga</string> + <string name="error_41">See piirkond pole serveri poolt toetatud</string> + <string name="title_select_date">Vali väljumise kuupäev</string> + <string name="clear_date_selection">Tühjenda</string> + <string name="title_filter">Filtreeri</string> + <string name="filtered">Filtreeritud</string> + <string name="title_filter_byline">Filtreeri liini alusel</string> + <string name="title_filter_bytime">Filtreeri aja alusel</string> + <string name="favourite">Lemmik</string> + <string name="title_select_time_start">Vali algusaeg</string> + <string name="title_select_time_end">Vali lõpuaeg</string> + <string name="alert_header">Olekute uuendused</string> + <string name="map_attribution"><![CDATA[© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>i kaasautorid]]></string> + <string name="favourite_content_description">Salvesta lemmikuna</string> + <string name="unfiltered">Filtreerimata</string> + <string name="cannot_save_favourite">Lemmiku salvestamine ei õnnestunud</string> + <string name="units_title">Mõõtühikud</string> + <string name="units_metric">Meetermõõdustik (SI)</string> + <string name="error_44">Rohkem väljumisi pole</string> + <string name="loading">laadime…</string> + <string name="favourite_deleted">Lemmik on kustutatud</string> + <string name="undo">Võta tegevus tagasi</string> + <string name="units_customary">USA kohandatud mõõtühikud</string> + <string name="title_settings">Seadistused</string> + <string name="no_geocoding_data">Geokodeerimise andmed puuduvad</string> + <string name="saving_cities_list">salvestame linnade loendit</string> + <string name="downloading_cities_list">laadime alla linnade loendit</string> + <string name="finished_updating_geocoding_data">Geokodeerimise andmete uuendamine on lõppenud</string> + <string name="updating_geocoding_data_failed">Geokodeerimise andmete uuendamine ei õnnestunud</string> + <string name="six">kuus</string> + <string name="seven">seitse</string> + <string name="nine">üheksa</string> + <string name="ten">kümme</string> + <string name="eight">kaheksa</string> + <string name="email_button_description">e-posti link</string> + <string name="alerts">Hoiatused</string> + <string name="hide">peida</string> + <string name="line_decorations">Liini nime kujundus</string> + <string name="show">näita</string> + <string name="matrix_button_description">Matrixi kanali link</string> + <string name="transitous_attribution">Transitouse (https://transitous.org) APIt vahendab Spline (https://routing.spline.de). Piirkondade (https://github.com/public-transport/transitous/tree/main/feeds) andmekogu haldab kogukond.</string> + <string name="credits">Yellowcircle8 kirjatüüp (https://git.apiote.xyz/yellowcircle8.git) põhineb Railway Sansil © Greg Fleming, OFL-1.1 https://github.com/davelab6/Railway-Sans\n\n Mastodoni ikoon (https://github.com/mastodon/joinmastodon) © Mastodoni kaasautorid, AGPL-3.0-or-later\n\n Bimba logo autor on https://github.com/tebriz159\n\n Material kujunduse ikoonid © Google, Apache-2.0\n\n Kaardiandmed © OpenStreetMapi kaasautorid (https://www.openstreetmap.org/copyright), ODbL-1.0\n\n OLC-koodide geokodeerimiseks vajalik linnade loend © Geonames (https://geonames.org), CC BY\n\n Matrixi logo ™/® Matrix.org</string> + <string name="trin">trin</string> + <string name="hes">hes</string> + <string name="quen">quen</string> + <string name="neen">neen</string> + <string name="ak">ak</string> + <string name="transitous_description">Kogukonna hallatav ja teenusepakkujatest sõltumatu rahvusvaheline ühistranspordi teekonnamootor. Teeninduspiirkonnad on kirjas lehel https://transitous.org/sources/</string> + <string name="stop_from_qr_code">Peatuse QR-kood</string> + <string name="no_geocoding_data_description">Päringus on OLC-kood ehk pluss-kood, aga geokodeerimiseks vajalik andmekogu puudub. Palun laadi vajalik andmekogu alla või luba seadistustest automaatsed uuendused.</string> + <string name="elv">elv</string> + <string name="zen">zen</string> + <string name="duna">duna</string> + <string name="quedra">quedra</string> + <string name="filtered_stop_question">Kas sa soovid valitud liinide kombinatsiooni salvestada lemmikuna?</string> + <string name="sev">sev</string> + <string name="dex">dex</string> + <string name="lef">lef</string> + <string name="none">puudub</string> + <string name="italics">kaldkiri</string> + <string name="colour">värv</string> + <string name="acra_notification_channel">Rakenduse kokkujooksmiste teavituskanal</string> + <string name="acra_notification_channel_description">Teavitused rakenduse kokkujooksmiste kohta, sealhulgas vastava aruande saatmise võimalus</string> + <string name="acra_notification_title">Bimba on kokku jooksnud</string> + <string name="acra_notification_text">Bimba teekonnale on ette jäänud ootamatu takistus ja rakendus on lõpetanud töö. Kas sa soovid selle kohta veateate saata?</string> + <string name="acra_notification_comment">Kommentaar on lisatud veateatele</string> + <string name="filtered_departures">Filtreeritud väljumised</string> + <string name="grey_out">märgitud halliks</string> + <string name="terminus_arrival_showing">Saabumised lõpp-punkti</string> +</resources> \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f229828d8dc9371528c4c32a6f7ab654b2860eec..604046478c874a3e78a2d33e137b169e1a3cbd7c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -33,7 +33,7 @@Arrêts à proximité <string name="line_headsigns_content_description">entre %1$s et %2$s</string> <string name="line_headsign_content_description">vers %1$s</string> <string name="line_headsigns">%1$s «» %2$s</string> - <string name="bimba_server_token_hint">Jeton</string> + <string name="bimba_server_token_hint">Jeton d\'identification</string> <string name="tickets_sold_content_description">Tickets vendus à bord</string> <string name="usb_charging_content_description">Charge USB</string> <string name="voice_announcements_content_description">Annonces vocales</string> @@ -63,17 +63,17 @@Montrer les départs <string name="realtime_content_description">Départ en temps réel</string> <string name="open_in_maps_app">Ouvrir dans une application de cartes</string> <string name="departure_now">Maintenant</string> - <string name="results_for">Résultats pour ‘%1$s’</string> + <string name="results_for">Résultats pour « %1$s »</string> <string name="at_time_realtime">à %1$02d:%2$02d:%3$02d</string> <string name="wheelchair_content_description">Le véhicule est accessible pour les fauteuils roulants</string> - <string name="departure_momentarily">Prochainement</string> + <string name="departure_momentarily">dans un instant</string> <string name="error_offline">Vous êtes hors ligne. Connectez-vous à Internet</string> <string name="off_boarding">Débarquement</string> <string name="error_gps">Impossible d\'obtenir la position actuelle</string> <string name="speed_in_km_per_h">%1$s km/h</string> <string name="occupancy_unknown">Inconnu</string> <string name="occupancy_few_seats">Peu de sièges</string> - <string name="occupancy_crowded">Encombré</string> + <string name="occupancy_crowded">bondé</string> <string name="occupancy_empty">Vide</string> <string name="occupancy_many_seats">Nombreux sièges</string> <string name="occupancy_full">Rempli</string> @@ -93,16 +93,16 @@Arrêt dans la zone %1$s <string name="stop_stub_on_demand">Arrêt à la demande</string> <string name="departure_headsign">» %1$s</string> <string name="translation_button_description">Lien vers le service de traduction</string> - <string name="app_description">Assistant de transport public libre ; un horaire dans votre poche.</string> + <string name="app_description">Assistant de transport public libre ; une fiche horaire dans votre poche.</string> <string name="error_41">Cette localité n\'est pas couverte par le serveur</string> - <string name="current_timetable_validity">Horraire valide : du %1$s au %2$s</string> + <string name="current_timetable_validity">Horaire valide : du %1$s au %2$s</string> <string name="filter_localities">Filtrer les localités</string> <string name="stop_from_qr_code">Code QR d\'arrêt</string> <string name="title_filter_byline">Filtrer par ligne</string> <string name="title_filter_bytime">Filtrer par horaire</string> <string name="title_select_time_end">Sélectionner l\'heure d\'arrivée</string> <string name="title_select_time_start">Sélectionner l\'heure de départ</string> - <string name="credits">Police yellowcircle8 (https://git.apiote.xyz/yellowcircle8.git) basée sur Railway Sans © Greg Fleming, OFL-1.1 https://github.com/davelab6/Railway-Sans\n\n Icône Mastodon (https://github.com/mastodon/joinmastodon) © Mastodon contributors, AGPL-3.0-or-later\n\n Logo Bimba créé par https://github.com/tebriz159\n\n Icônes Material © Google, Apache-2.0\n\n Données cartographiques © OpenStreetMap contributors, ODbL-1.0</string> + <string name="credits">Police yellowcircle8 (https://git.apiote.xyz/yellowcircle8.git) basée sur Railway Sans © Greg Fleming, OFL-1.1 https://github.com/davelab6/Railway-Sans\n\n Icône Mastodon (https://github.com/mastodon/joinmastodon) © contributeurs de Mastodon, AGPL-3.0-or-later\n\n Logo Bimba créé par https://github.com/tebriz159\n\n Icônes Material © Google, Apache-2.0\n\n Données cartographiques © contributeurs d’OpenStreetMap, ODbL-1.0\n\n Liste des villes utilisées pour le géocodage des codes short plus © Geonames (https://geonames.org), CC BY\n\n Logo Matrix™/® Matrix.org</string> <string name="error_400">L\'application a effectué une requête mal formulée</string> <string name="error_404">Pas trouvé</string> <string name="error_429">Limite dépassée. Réessayez plus tard</string> @@ -112,4 +112,134 @@En voiture tout le monde ! <string name="onboarding_simple">Simple</string> <string name="occupancy_wont_let">embarquement refusé</string> <string name="choose_server">Choix du type de serveur</string> -</resources> \ No newline at end of file + <string name="distance_in_m">%1$s m</string> + <plurals name="distance_in_km_cd"> + <item quantity="one">%1$d kilomètre</item> + <item quantity="many">%1$d kilomètres</item> + <item quantity="other">%1$d kilomètres</item> + </plurals> + <string name="distance_in_ft">%1$s ft</string> + <plurals name="time_in_s_cd"> + <item quantity="one">%1$d seconde</item> + <item quantity="many">%1$d secondes</item> + <item quantity="other">%1$d secondes</item> + </plurals> + <plurals name="speed_in_km_per_h_cd"> + <item quantity="one">%1$d kilomètre par heure</item> + <item quantity="many">%1$d kilomètres par heure</item> + <item quantity="other">%1$d kilomètres par heure</item> + </plurals> + <string name="favourite">Favori</string> + <string name="filtered">Filtré</string> + <string name="error_44">Plus de départ</string> + <string name="three">trois</string> + <string name="distance_in_gf">%1$s%2$sGf</string> + <string name="ten">dix</string> + <string name="cities_channel_description">Notifications indiquant l’avancement de la mise à jour des données locales de géocodage</string> + <string name="saving_cities_list">Enregistrement de la liste des villes</string> + <string name="updating_geocoding_data">Mise à jour des données de géocodage</string> + <string name="downloading_cities_list">téléchargement de la liste des villes</string> + <string name="two">deux</string> + <string name="elv">onze</string> + <string name="none">aucun</string> + <string name="hide">cacher</string> + <string name="colour">couleur</string> + <string name="show">montrer</string> + <string name="grey_out">griser</string> + <string name="filtered_departures">Départs filtrés</string> + <string name="local_time">heure locale</string> + <string name="speed_in_m_per_s">%1$s m/s</string> + <string name="speed_in_mi_per_h">%1$s mph</string> + <string name="server_rate_limited_question">Ce serveur est à taux limité et aucun jeton n’a été fourni. Voulez-vous continuer ?</string> + <string name="no_geocoding_data">Pas de données de géocodage</string> + <string name="error_geocoding">Ville introuvable</string> + <string name="four">quatre</string> + <string name="five">cinq</string> + <string name="six">six</string> + <string name="seven">sept</string> + <string name="eight">huit</string> + <string name="nine">neuf</string> + <plurals name="distance_in_m_cd"> + <item quantity="one">%1$d mètre</item> + <item quantity="many">%1$d mètres</item> + <item quantity="other">%1$d mètres</item> + </plurals> + <plurals name="distance_in_yd_cd"> + <item quantity="one">%1$d yard</item> + <item quantity="many">%1$d yards</item> + <item quantity="other">%1$d yards</item> + </plurals> + <plurals name="distance_in_ft_cd"> + <item quantity="one">%1$d pied</item> + <item quantity="many">%1$d pieds</item> + <item quantity="other">%1$d pieds</item> + </plurals> + <plurals name="distance_in_mi_cd"> + <item quantity="one">%1$d mille</item> + <item quantity="many">%1$d milles</item> + <item quantity="other">%1$d milles</item> + </plurals> + <plurals name="speed_in_m_per_s_cd"> + <item quantity="one">%1$d mètre par seconde</item> + <item quantity="many">%1$d mètres par seconde</item> + <item quantity="other">%1$d mètres par seconde</item> + </plurals> + <plurals name="speed_in_mi_per_h_cd"> + <item quantity="one">%1$d mille par heure</item> + <item quantity="many">%1$d milles par heure</item> + <item quantity="other">%1$d milles par heure</item> + </plurals> + <string name="congestion_stop_and_go">en accordéon</string> + <string name="onboarding_question">Comment souhaitez-vous commencer ?</string> + <string name="rate_limit">Taux limite</string> + <string name="error_traffic_spec">Impossible de vérifier le serveur</string> + <string name="error_url">URL non conforme fournie</string> + <string name="clear_date_selection">Effacer</string> + <string name="alert_header">Mise à jour du statut</string> + <string name="distance_in_km">%1$s km</string> + <string name="distance_in_yd">%1$s yd</string> + <string name="distance_in_mi">%1$s mi</string> + <string name="distance_in_two_units_cd">%1$s et %2$s</string> + <string name="time_in_s">%1$s s</string> + <string name="map_attribution">© contributeurs d’<a href=https://www.openstreetmap.org/copyright>OpenStreetMap</a></string> + <string name="no_email_app">Aucune application d’e-mail installée</string> + <string name="favourite_content_description">Enregistrer comme favori</string> + <string name="unfiltered">Non filtré</string> + <string name="cannot_save_favourite">Impossible d’enregistrer le favori</string> + <string name="loading">chargement…</string> + <string name="favourite_deleted">Favori supprimé</string> + <string name="undo">Annuler</string> + <string name="units_title">Système d’unités</string> + <string name="units_locale_based">Basé sur le système</string> + <string name="units_metric">Métrique (SI)</string> + <string name="units_imperial">Impérial (Royaume-Uni)</string> + <string name="units_customary">Américain (États-Unis)</string> + <string name="units_tgm10">TGM (base 10)</string> + <string name="units_tgm12">TGM (base 12)</string> + <string name="title_settings">Paramètres</string> + <string name="cities_channel_name">Fil de mise à jour des villes</string> + <string name="finished_updating_geocoding_data">Mise à jour des données de géocodage terminée</string> + <string name="updating_geocoding_data_failed">Mise à jour des données de géocodage échouée</string> + <string name="zero">zéro</string> + <string name="one">un</string> + <string name="filtered_stop_question">Voulez-vous enregistrer un favori filtré avec des lignes sélectionnées ?</string> + <string name="line_decorations">Décorations du nom de la ligne</string> + <string name="acra_notification_channel">Fil des rapports de problèmes</string> + <string name="acra_notification_channel_description">Notifications indiquant les problèmes et permettant d\'envoyer des rapports de problèmes</string> + <string name="acra_notification_title">Bimba s’est arrêté</string> + <string name="acra_notification_text">Un blocage inattendu s\'est dressé sur le chemin de Bimba. Voulez-vous envoyer un rapport ?</string> + <string name="send">Envoyer</string> + <string name="discard">Supprimer</string> + <string name="send_with_comment">Envoyer avec commentaire</string> + <string name="acra_notification_comment">Commentaire ajouté au rapport de problème</string> + <string name="alerts">Alertes</string> + <string name="terminus_arrival_showing">Arrivées au terminus</string> + <string name="matrix_button_description">lien vers le salon Matrix</string> + <string name="email_button_description">lien vers le courriel</string> + <string name="transitous_description">Un service de transport public international, neutre sur le plan des fournisseurs et géré par la communauté. La couverture est disponible à l\'adresse suivante : https://transitous.org/sources/</string> + <string name="transitous_attribution">API Transitous (https://transitous.org) fournie par Spline (https://routing.spline.de). Localités (https://github.com/public-transport/transitous/tree/main/feeds) maintenues par la communauté.</string> + <string name="no_geocoding_data_description">La requête contient un code short plus mais il n\'y a pas de données de géocodage présentes. Téléchargez les données de géocodage ou activez leur mise à jour automatique dans les paramètres.</string> + <string name="congestion_congestion">ralentissements</string> + <string name="about_time">environ %1$02d:%2$02d</string> + <string name="italics">italique</string> +</resources> diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index a583c09cc1089d2f2f972a9b0596380c0a308b7e..9e162712580cf6ac01c38c1dec5c8a8337d52f9f 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -48,7 +48,7 @@za moment <string name="departure_departed">odjechał</string> <string name="departure_now">teraz</string> <string name="at_time">o %1$02d:%2$02d</string> - <string name="about_time">about %1$02d:%2$02d</string> + <string name="about_time">około %1$02d:%2$02d</string> <string name="at_time_realtime">o %1$02d:%2$02d:%3$02d</string> <string name="on_demand">na żądanie</string> <string name="no_boarding">brak</string> @@ -64,8 +64,7 @@Wyniki dla „%1$s” <string name="bimba_server_address_hint">Serwer</string> <string name="bimba_server_token_hint">Żeton</string> <string name="realtime_content_description">odjazd w czasie rzeczywistym</string> - <string name="exact_content_description">czas odjazdu jest dokładny z rozkładu</string> - <string name="inexact_content_description">czas odjazdu jest przybliżony</string> + <string name="schedule_content_description">czas odjazdu jest z rozkładu</string> <string name="wheelchair_content_description">pojazd ma niską podłogę</string> <string name="air_condition_content_description">klimatyzacja</string> <string name="bicycles_allowed_content_description">przewóz rowerów dozwolony</string> @@ -303,4 +302,10 @@link do e-maila <string name="no_email_app">Brak aplikacji e-mail</string> <string name="transitous_attribution">API Transitous (https://transitous.org) dostarczane przez Spline (https://routing.spline.de). Lokalizacje (https://github.com/public-transport/transitous/tree/main/feeds) utrzymywane przez społeczność.</string> <string name="local_time">czas lokalny</string> + <string name="departure_arrived">przyjechał</string> + <string name="arrival_approximate">przyb. przyj.</string> + <string name="arrival">przyjazd</string> + <string name="departure_approximate">przyb. odj.</string> + <string name="departure">odjazd</string> + <string name="approximately">w przybliżeniu</string> </resources> \ No newline at end of file diff --git a/app/src/main/res/values-v31/themes.xml b/app/src/main/res/values-v31/themes.xml index 1b04dfb059a09665e1aa20100b1a0e4b5f19d4cb..f07ff67b177ed5e11ed481990ae1e34133dc4e3c 100644 --- a/app/src/main/res/values-v31/themes.xml +++ b/app/src/main/res/values-v31/themes.xml @@ -58,12 +58,12 @@- 9sp
</style> <style name="Theme.Bimba.Splash" parent="Theme.SplashScreen"> - <item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item> - <item name="windowSplashScreenIconBackgroundColor">@color/ic_launcher_background</item> + <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item> + <item name="windowSplashScreenBackground">?attr/colorSurface</item> <item name="postSplashScreenTheme">@style/Theme.Bimba</item> </style> <style name="Preference.SwitchPreferenceCompat" parent="@style/Preference.SwitchPreferenceCompat.Material" tool:ignore="ResourceCycle"> <item name="widgetLayout">@layout/preferences_switch_material</item> </style> -</resources> \ No newline at end of file +</resources> diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml index 52ded369d35deb8e357f2bba5c042a0adc2de048..c590b8026cb06e551b4fc892f4f8c1065b4166e6 100644 --- a/app/src/main/res/xml/locales_config.xml +++ b/app/src/main/res/xml/locales_config.xml @@ -8,9 +8,11 @@ --> <locale-config xmlns:android="http://schemas.android.com/apk/res/android"> <locale android:name="en"/> - <locale android:name="pl"/> - <locale android:name="it"/> <locale android:name="de"/> - <locale android:name="fr"/> + <locale android:name="en-rGB"/> <locale android:name="en-rUS"/> + <locale android:name="et"/> + <locale android:name="fr"/> + <locale android:name="it"/> + <locale android:name="pl"/> </locale-config> \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 7a3bc819960b47c4f4e7c762aa8cc8e828d14f11..86f0ddbf3403895e1c7ff8b91dd0849b8edda743 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,8 +4,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id("com.android.application") version "8.7.0" apply false - id("com.android.library") version "8.7.0" apply false + id("com.android.application") version "8.7.2" apply false + id("com.android.library") version "8.7.2" apply false kotlin("android") version "2.0.10" apply false kotlin("jvm") version "1.7.20" apply false kotlin("plugin.parcelize") version "1.8.20" apply false diff --git a/fruchtfleisch/build.gradle.kts b/fruchtfleisch/build.gradle.kts index 014557871091925f8b0568606aea1e74ec7837d9..df25428f756486a6fc35db26cf06914a5427ee12 100644 --- a/fruchtfleisch/build.gradle.kts +++ b/fruchtfleisch/build.gradle.kts @@ -15,8 +15,8 @@ //implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.10") } java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } tasks.withType<Test> { diff --git a/metadata/de-DE/short_description.txt b/metadata/de-DE/short_description.txt new file mode 100644 index 0000000000000000000000000000000000000000..98c1bbc4e65617a72f837c7687302eb60410e04a --- /dev/null +++ b/metadata/de-DE/short_description.txt @@ -0,0 +1 @@ +Open Source ÖPNV-Begleiter; der Fahrplan für deine Tasche. diff --git a/metadata/en/changelogs/33.txt b/metadata/en/changelogs/33.txt new file mode 100644 index 0000000000000000000000000000000000000000..2373678058a8b01c40301f6d459695a67eb52f91 --- /dev/null +++ b/metadata/en/changelogs/33.txt @@ -0,0 +1,5 @@ +* updated dependencies +* prepared for separate arrival and departure times +* improve styling +* added Estonian language (Priit Jõerüüt) +* improve translations (Lars K, Nicolas DERIVE, stormax181iq) diff --git a/metadata/en-US/changelogs/33.txt b/metadata/en-US/changelogs/33.txt new file mode 100644 index 0000000000000000000000000000000000000000..2373678058a8b01c40301f6d459695a67eb52f91 --- /dev/null +++ b/metadata/en-US/changelogs/33.txt @@ -0,0 +1,5 @@ +* updated dependencies +* prepared for separate arrival and departure times +* improve styling +* added Estonian language (Priit Jõerüüt) +* improve translations (Lars K, Nicolas DERIVE, stormax181iq) diff --git a/metadata/fr-FR/changelogs/25.txt b/metadata/fr-FR/changelogs/25.txt new file mode 100644 index 0000000000000000000000000000000000000000..9be56df711665b506f2ae6436dd212effaeaa0c0 --- /dev/null +++ b/metadata/fr-FR/changelogs/25.txt @@ -0,0 +1,11 @@ +Changements en version 3.3 +* Ajout de la sélection de la date et du filtrage par heure +* Ajout du filtrage des départs par ligne +* Ajout d’alertes affichées sur les arrêts et les départs +* Correction de la version paysage de l’écran "à propos" +* Correction des capacités des véhicules sur la carte +* Changement des localités cachées vers un plus faible contraste +* Correction de l’affichage des lignes autres que 2 +* Correction de l’enregistrement du cache des localités +* Mise à jour des dépendances +* Mise à jour des méthodes obsolètes dans le code diff --git a/metadata/fr-FR/changelogs/26.txt b/metadata/fr-FR/changelogs/26.txt new file mode 100644 index 0000000000000000000000000000000000000000..256b9c9bbb7dab7d340faf7ac1382dcaa7ccac03 --- /dev/null +++ b/metadata/fr-FR/changelogs/26.txt @@ -0,0 +1,13 @@ +Changements en version 3.3.1 +* Correction d’un problème en zoomant trop la carte +Changements en version 3.3 +* Ajout de la sélection de la date et du filtrage par heure +* Ajout du filtrage des départs par ligne +* Ajout d’alertes affichées sur les arrêts et les départs +* Correction de la version paysage de l’écran "à propos" +* Correction des capacités des véhicules sur la carte +* Changement des localités cachées vers un plus faible contraste +* Correction de l’affichage des lignes autres que 2 +* Correction de l’enregistrement du cache des localités +* Mise à jour des dépendances +* Mise à jour des méthodes obsolètes dans le code diff --git a/metadata/fr-FR/changelogs/27.txt b/metadata/fr-FR/changelogs/27.txt new file mode 100644 index 0000000000000000000000000000000000000000..d6059cb8f810bcc312f793b418e8ffbce730f4b9 --- /dev/null +++ b/metadata/fr-FR/changelogs/27.txt @@ -0,0 +1,16 @@ +Changements en version 3.3.2 +* Ajout d’une attribution Openstreetmap correcte +* Changement du zoom minimum de la carte +Changements en version 3.3.1 +* Correction d’un problème en zoomant trop la carte +Changements en version 3.3 +* Ajout de la sélection de la date et du filtrage par heure +* Ajout du filtrage des départs par ligne +* Ajout d’alertes affichées sur les arrêts et les départs +* Correction de la version paysage de l’écran "à propos" +* Correction des capacités des véhicules sur la carte +* Changement des localités cachées vers un plus faible contraste +* Correction de l’affichage des lignes autres que 2 +* Correction de l’enregistrement du cache des localités +* Mise à jour des dépendances +* Mise à jour des méthodes obsolètes dans le code diff --git a/metadata/fr-FR/changelogs/28.txt b/metadata/fr-FR/changelogs/28.txt new file mode 100644 index 0000000000000000000000000000000000000000..8f891b044de8d78a478943ad9d1f702704d159eb --- /dev/null +++ b/metadata/fr-FR/changelogs/28.txt @@ -0,0 +1,8 @@ +Changements en version 3.4 +* Ajout d’un compte à rebours pour montrer la prochaine mise à jour des départs +* Correction des filtres et feuilles de fond persistants lors de changements d’écran +* Changement de la disposition des alertes au-dessus des départs +* Correction des résultats de recherche fantômes +* Correction de la mise en page des paysages et du bord à bord +* Ajout simple des favoris +* Ajout de la traduction française (par ArnaudDvs) diff --git a/metadata/fr-FR/changelogs/29.txt b/metadata/fr-FR/changelogs/29.txt new file mode 100644 index 0000000000000000000000000000000000000000..b8f0db227ada8de170f9e609f90f6f329a0ed361 --- /dev/null +++ b/metadata/fr-FR/changelogs/29.txt @@ -0,0 +1,4 @@ +Changes in version 3.5: +* ajout d’une recherche via Plus Codes courts +* ajouts de flèches indiquant l’arrêt le plus proche +* ajout des unités (vitesse, distance, temps) diff --git a/metadata/fr-FR/changelogs/30.txt b/metadata/fr-FR/changelogs/30.txt new file mode 100644 index 0000000000000000000000000000000000000000..cd16155f45cd1f6bd43a5c2e73a44b5f5f899270 --- /dev/null +++ b/metadata/fr-FR/changelogs/30.txt @@ -0,0 +1,5 @@ +Changements en version 3.6: +* Changements dans les paramètres pour pouvoir montrer les lignes en italique +* Les problèmes/crashs peuvent être signalés +* La page « à propos » affiche plus de points de contact +* Correction de la mise à jour des favoris et des noms géographiques sur les anciennes versions d’Android diff --git a/metadata/fr-FR/changelogs/31.txt b/metadata/fr-FR/changelogs/31.txt new file mode 100644 index 0000000000000000000000000000000000000000..cd16155f45cd1f6bd43a5c2e73a44b5f5f899270 --- /dev/null +++ b/metadata/fr-FR/changelogs/31.txt @@ -0,0 +1,5 @@ +Changements en version 3.6: +* Changements dans les paramètres pour pouvoir montrer les lignes en italique +* Les problèmes/crashs peuvent être signalés +* La page « à propos » affiche plus de points de contact +* Correction de la mise à jour des favoris et des noms géographiques sur les anciennes versions d’Android diff --git a/metadata/pl-PL/changelogs/33.txt b/metadata/pl-PL/changelogs/33.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b61d6517e93169f3833d5e9fa8430770d139962 --- /dev/null +++ b/metadata/pl-PL/changelogs/33.txt @@ -0,0 +1,5 @@ +* zaktualizowano zależności +* przygotowano pod oddzielne czasy przyjazdu i odjazdu +* poprawiono ostylowanie +* dodano język estoński (Priit Jõerüüt) +* poprawiono tłumaczenia (Lars K, Nicolas DERIVE, stormax181iq) diff --git a/release.sh b/release.sh index 528c6853c80625ca544bd4addf3b535280ea079b..7b8c6671ca16a510eb4014d883fdcc84505f215c 100755 --- a/release.sh +++ b/release.sh @@ -98,7 +98,7 @@ sed -i "s/versionCode = $currentVersionCode/versionCode = $newVersionCode/" app/build.gradle.kts git shortlog "v${currentVersionName}..HEAD" >> "metadata/en-US/changelogs/$newVersionCode.txt" - echo "time to update changelogs" + echo "time to update changelogs and README" elif [ $phase -eq 1 ] then newVersionName=$(grep -Eo 'versionName = "[0-9\.]+"' app/build.gradle.kts | cut -d '=' -f2 | tr -d ' "') @@ -114,6 +114,7 @@ fi fi git add app/build.gradle.kts git add metadata/ + git add README.adoc git commit -S -m "release version $newVersionName ($newVersionCode)" || true echo 'pushing …' git push