Author: Adam Evyčędo <git@apiote.xyz>
merge develop into master for version 3.9.0-rc.2
%!v(PANIC=String method: strings: negative Repeat count)
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 4c4f412fafbcd7a61baecb8ed4e14734b604c450..4e291197dd184e9aae4739b7b9102e4c2759de9e 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -14,13 +14,20 @@ * Travel planning * Offline timetable -== [3.9.0] – 2025-02-08 +== [3.9.0] – 2025-xx-xx === Added * Travel planning based on Transitous -== [3.6.1] – 2024-09-04 +== [3.8.0] – 2025-01-21 + +=== Changed + +* separated arrivals and departures +* switched to Transitous MOTIS 2 API + +== [3.7.0] – 2024-10-15 === Fixed diff --git a/README.adoc b/README.adoc index 911bd206a8b9b12526d94e40597541b17bee5bb3..dd2f04766ac9ef8678baf589cd7a8b819e7d02da 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.9.0-rc.1 2025-02-08 +v3.9.0-rc.3 2025-03-12 :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 cef626c86995282d54924611ad1a8f66dce60045..b8bc7888e2be37668b6401d107b9212e643f9613 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -21,14 +21,14 @@ android { namespace = "xyz.apiote.bimba.czwek" // NOTE apksigner with `--alignment-preserved` https://gitlab.com/fdroid/fdroiddata/-/issues/3299#note_1989808414 compileSdk = 35 - buildToolsVersion = "35.0.0" + buildToolsVersion = "35.0.1" defaultConfig { applicationId = "xyz.apiote.bimba.czwek" minSdk = 21 targetSdk = 35 - versionCode = 35 - versionName = "3.9.0-rc.1" + versionCode = 36 + versionName = "3.9.0-rc.2" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" resourceConfigurations += listOf("en", "de", "en-rGB", "en-rUS", "et", "fr", "it", "pl", "ru", "ta") @@ -98,17 +98,17 @@ dependencies { 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.2.0") + implementation("androidx.constraintlayout:constraintlayout:2.2.1") 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.6") - implementation("androidx.navigation:navigation-ui-ktx:2.8.6") + implementation("androidx.navigation:navigation-fragment-ktx:2.8.8") + implementation("androidx.navigation:navigation-ui-ktx:2.8.8") 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.10.0") + implementation("org.yaml:snakeyaml:2.4") + implementation("androidx.activity:activity-ktx:1.10.1") implementation("com.otaliastudios:zoomlayout:1.9.0") implementation("dev.bandb.graphview:graphview:0.8.1") implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.8.0") @@ -123,9 +123,9 @@ implementation("ch.acra:acra-http:5.12.0") implementation("ch.acra:acra-notification:5.12.0") implementation("com.squareup.okhttp3:okhttp:4.12.0") implementation("com.squareup.moshi:moshi-kotlin:1.15.2") - implementation("androidx.activity:activity:1.10.0") + implementation("androidx.activity:activity:1.10.1") - coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4") + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5") androidTestImplementation("androidx.test.ext:junit:1.2.1") androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1") diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/RoundedBackgroundSpan.kt b/app/src/main/java/xyz/apiote/bimba/czwek/RoundedBackgroundSpan.kt index e38daad84e9aba836e3195be5c442c0abf6aa678..b410764e4abb270111a89221bf2c8fe6b5198b4d 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/RoundedBackgroundSpan.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/RoundedBackgroundSpan.kt @@ -9,7 +9,13 @@ import android.graphics.Paint import android.graphics.RectF import android.text.style.ReplacementSpan -class RoundedBackgroundSpan(private val bgColour: Int, private val fgColour: Int) : ReplacementSpan() { +class RoundedBackgroundSpan(private val bgColour: Int, private val fgColour: Int) : + ReplacementSpan() { + + companion object { + const val PADDING = 20 // TODO based on small text, make dependent on eg. em-dash length + } + override fun getSize( paint: Paint, text: CharSequence, @@ -17,7 +23,15 @@ start: Int, end: Int, fm: Paint.FontMetricsInt? ): Int { - return (paint.measureText(text, start, end)+20).toInt() + val l = paint.measureText(text, start, end) + PADDING + if (fm != null) { + fm.ascent = paint.fontMetrics.ascent.toInt() + fm.bottom = paint.fontMetrics.bottom.toInt() + fm.descent = paint.fontMetrics.descent.toInt() + fm.leading = paint.fontMetrics.leading.toInt() + fm.top = paint.fontMetrics.top.toInt() + } + return l.toInt() } override fun draw( @@ -31,12 +45,19 @@ y: Int, bottom: Int, paint: Paint ) { - val length = paint.measureText(text, start, end) + 20 - val rect = RectF(x, top.toFloat() - 5f, x + length, y.toFloat() + 5f) + val length = paint.measureText(text, start, end) + PADDING + /* + Log.i("BackgroundSpan", "x: $x, y: $y, start: $start, end: $end, top: $top, bottom: $bottom") + Log.i("BackgroundSpan", "text: $text, length: $length") + Log.i("BackgroundSpan", "fontMetrics:: bottom: ${paint.fontMetricsInt.bottom}, top: ${paint.fontMetricsInt.top}, ascent: ${paint.fontMetricsInt.ascent}, descent: ${paint.fontMetricsInt.descent}, leading: ${paint.fontMetricsInt.leading}") + Log.i("BackgroundSpan", "fontSpacing: ${paint.fontSpacing}; 1dp=${dpToPixelI(1f)}") + */ + val height = y - top + val rect = RectF(x, top.toFloat()-(height/6), x + length, y.toFloat()+(height/6)) paint.color = bgColour - canvas.drawRoundRect(rect, 10f, 10f, paint) + canvas.drawRoundRect(rect, height/4f, height/4f, paint) paint.color = fgColour paint.textAlign = Paint.Align.CENTER - canvas.drawText(text, start, end, x+(length/2), y.toFloat(), paint) + canvas.drawText(text, start, end, x + (length / 2), y.toFloat(), paint) } } \ No newline at end of file diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/journeys/Journeys.kt b/app/src/main/java/xyz/apiote/bimba/czwek/journeys/Journeys.kt index ff1d71676d397e60dcf7203f80d6cfa180069dc9..2f4d18ccb8bbebd0cd076fefb7d802efd9acc97e 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/journeys/Journeys.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/journeys/Journeys.kt @@ -6,6 +6,7 @@ package xyz.apiote.bimba.czwek.journeys import android.annotation.SuppressLint import android.content.Context +import android.text.SpannableStringBuilder import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -17,6 +18,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder import com.google.android.material.card.MaterialCardView import xyz.apiote.bimba.czwek.R import xyz.apiote.bimba.czwek.repo.Journey +import xyz.apiote.bimba.czwek.repo.Stop.LineDecoration import xyz.apiote.bimba.czwek.units.UnitSystem class JourneysViewHolder(itemView: View) : ViewHolder(itemView) { @@ -43,8 +45,19 @@ holder.startTime.text = context.getString(R.string.time, journey.startTime.hour, journey.startTime.minute) holder.endTime.text = context.getString(R.string.time, journey.endTime.hour, journey.endTime.minute) - holder.lines.text = - journey.legs.map { it.start.vehicle.Line.name }.filter { it.isNotBlank() }.joinToString() + holder.lines.text = journey.legs.filter { it.start.vehicle.Line.name.isNotBlank() } + .fold(SpannableStringBuilder("")) { acc, leg -> + if (acc.isNotBlank()) { + acc.append(" ") + } + val s = leg.start.vehicle.Line.decorate( + SpannableStringBuilder(leg.start.vehicle.Line.name), + LineDecoration.COLOUR, + null + ) + acc.append(s) + acc + } holder.legs.removeAllViews() journey.legs.forEach { @@ -98,7 +111,11 @@ context.getString(R.string.journey_stops_headsign, stops, headsign) } val legDestination = legView.findViewById<TextView>(R.id.leg_destination) - if (it.destination.stop.name.isBlank() || it.destination.stop.name in arrayOf("START", "END")) { + if (it.destination.stop.name.isBlank() || it.destination.stop.name in arrayOf( + "START", + "END" + ) + ) { legDestination.visibility = View.GONE } else { legDestination.apply { diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/journeys/JourneysViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/journeys/JourneysViewModel.kt index 961dd33b1e600b758ad71fb0098aeb8925628eb8..8f54abe1ac6a5e29c1d615a22b523201afad8fd2 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/journeys/JourneysViewModel.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/journeys/JourneysViewModel.kt @@ -10,6 +10,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch +import org.openapitools.client.infrastructure.ServerException import xyz.apiote.bimba.czwek.repo.Journey import xyz.apiote.bimba.czwek.repo.JourneyParams import xyz.apiote.bimba.czwek.repo.Place @@ -20,7 +21,6 @@ private val _journeys = MutableLiveData<List<Journey>>() val journeys: LiveData<List<Journey>> = _journeys - // FIXME when not in foreground, throws java.net.SocketException: Software caused connection abort fun getJourneys(context: Context, origin: Place, destination: Place, params: JourneyParams) { viewModelScope.launch { try { @@ -29,6 +29,12 @@ xyz.apiote.bimba.czwek.api.getJourney(origin, destination, params, context) } catch (e: SocketTimeoutException) { _journeys.value = emptyList<Journey>() Log.e("Journeys", "timeout: $e") + } catch (e: ServerException) { + _journeys.value = emptyList<Journey>() + Log.w("Suggestion", "Transitous returned: ${e.statusCode}, ${e.message}") + } catch (e: Exception) { + _journeys.value = emptyList<Journey>() + Log.w("Suggestion", "Exception: $e") } } } diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineStub.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineStub.kt index 86565ae24cf1322fba82acae25063e71bb026d28..26b4b729f25698d95be373a282a99c6066da3fb9 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineStub.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/LineStub.kt @@ -5,13 +5,21 @@ package xyz.apiote.bimba.czwek.repo import android.content.Context -import android.graphics.drawable.BitmapDrawable +import android.graphics.Typeface import android.graphics.drawable.Drawable import android.os.Parcelable +import android.text.Annotation +import android.text.SpannableStringBuilder +import android.text.Spanned +import android.text.style.StyleSpan +import android.util.Log +import androidx.core.graphics.drawable.toDrawable import kotlinx.parcelize.Parcelize +import xyz.apiote.bimba.czwek.RoundedBackgroundSpan import xyz.apiote.bimba.czwek.api.LineStubV1 import xyz.apiote.bimba.czwek.api.LineStubV2 import xyz.apiote.bimba.czwek.api.LineStubV3 +import xyz.apiote.bimba.czwek.repo.Stop.LineDecoration @Parcelize data class LineStub(val name: String, val kind: LineType, val colour: Colour) : LineAbstract, Parcelable { @@ -20,6 +28,45 @@ constructor(l: LineStubV2) : this(l.name, LineType.of(l.kind), Colour(l.colour)) constructor(l: LineStubV3) : this(l.name, LineType.of(l.kind), Colour(l.colour)) fun icon(context: Context, scale: Float = 1f): Drawable { - return BitmapDrawable(context.resources, super.icon(context, kind, colour, scale)) + return super.icon(context, kind, colour, scale).toDrawable(context.resources) + } + + fun decorate( + str: SpannableStringBuilder, + decoration: LineDecoration, + annotation: Annotation? + ): SpannableStringBuilder { + val spanStart = if (annotation != null) { + str.getSpanStart(annotation) + } else { + 0 + } + val spanEnd = if (annotation != null) { + str.getSpanEnd(annotation) + } else { + str.length + } + + val background = RoundedBackgroundSpan(colour.toInt(), textColour(colour)) + val ital = StyleSpan(Typeface.ITALIC) + when (decoration) { + LineDecoration.ITALICS -> str.setSpan( + ital, + spanStart, spanEnd, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ) + + LineDecoration.COLOUR -> { + str.setSpan( + background, + spanStart, spanEnd, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ) + } + + LineDecoration.NONE -> {} + } + + return str } } \ No newline at end of file diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt index 1f0f19b8282e80f48a826ec163380a09b270afc6..6359c8153f193f226c7a4665a8760bd266f4c79c 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Stop.kt @@ -5,19 +5,15 @@ package xyz.apiote.bimba.czwek.repo import android.content.Context -import android.graphics.Typeface import android.graphics.drawable.Drawable import android.os.Parcelable import android.text.Annotation import android.text.Spannable import android.text.SpannableStringBuilder -import android.text.Spanned import android.text.SpannedString -import android.text.style.StyleSpan import androidx.preference.PreferenceManager import kotlinx.parcelize.Parcelize import xyz.apiote.bimba.czwek.R -import xyz.apiote.bimba.czwek.RoundedBackgroundSpan import xyz.apiote.bimba.czwek.api.StopV1 import xyz.apiote.bimba.czwek.api.StopV2 import xyz.apiote.bimba.czwek.api.StopV3 @@ -167,29 +163,7 @@ "decoration" -> { if (args.isNotEmpty()) { return@forEach } - // TODO rounded corners/padding - val background = RoundedBackgroundSpan(line.colour.toInt(), line.textColour(line.colour)) - val ital = StyleSpan(Typeface.ITALIC) - when (decoration) { - LineDecoration.ITALICS -> str.setSpan( - ital, - str.getSpanStart(it), - str.getSpanEnd(it), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE - ) - - LineDecoration.COLOUR -> { - str.setSpan( - background, - str.getSpanStart(it), - str.getSpanEnd(it), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE - ) - // str.setSpan(foreground, str.getSpanStart(it), str.getSpanEnd(it), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) - } - - LineDecoration.NONE -> {} - } + line.decorate(str, decoration, it) } } } @@ -215,10 +189,10 @@ companion object { fun fromPreferences(context: Context) = when (PreferenceManager.getDefaultSharedPreferences(context) .getString("line_decoration", "italics")) { - "italics" -> Stop.LineDecoration.ITALICS - "colour" -> Stop.LineDecoration.COLOUR - "none" -> Stop.LineDecoration.NONE - else -> Stop.LineDecoration.ITALICS + "italics" -> ITALICS + "colour" -> COLOUR + "none" -> NONE + else -> ITALICS } } } diff --git a/app/src/main/res/layout/journey.xml b/app/src/main/res/layout/journey.xml index be5120d120ac8514a2a112c47feef904733d0a6b..3ee0cb0a56ec6137a7dc092b3796f6ac35ed865d 100644 --- a/app/src/main/res/layout/journey.xml +++ b/app/src/main/res/layout/journey.xml @@ -25,17 +25,21 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" tools:text="11:25" /> + <!-- TODO line height multiplier --> <com.google.android.material.textview.MaterialTextView android:id="@+id/lines" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" + android:layout_marginStart="8dp" + android:layout_marginTop="4dp" + android:layout_marginEnd="8dp" + android:lineSpacingExtra="18sp" + android:padding="4dp" android:textAlignment="center" android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" - app:layout_constraintEnd_toStartOf="@+id/end_time" - app:layout_constraintStart_toEndOf="@+id/start_time" - app:layout_constraintTop_toTopOf="@+id/start_time" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/start_time" tools:text="Metropolitan, Circle, Hammersmith&City" /> <com.google.android.material.textview.MaterialTextView @@ -44,7 +48,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toTopOf="@+id/lines" + app:layout_constraintTop_toTopOf="@+id/start_time" tools:text="12:30" /> <LinearLayout diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index a4545ae29ca307e330a99ba00ef35bb4082f99ee..f7eef407a55811571f2891156a693fa0affa2925 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -25,7 +25,7 @@Parti <string name="at_time">à %1$02d:%2$02d</string> <string name="departure_headsign_content_description">vers %1$s</string> <string name="on_demand">à la demande</string> - <string name="no_boarding">pas d\'embarquement</string> + <string name="no_boarding">pas d’embarquement</string> <string name="on_boarding">Embarquement</string> <string name="boarding">Embarquement possible</string> <string name="line_headsign">» %1$s</string> @@ -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 d\'identification</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> @@ -42,13 +42,13 @@Avancé <string name="title_feeds">Horaires</string> <string name="error">Erreur</string> <string name="onboarding_advanced_action">Choisir un serveur</string> - <string name="server_private_question">Ce serveur est privé et aucun jeton n\'a été fourni</string> + <string name="server_private_question">Ce serveur est privé et aucun jeton n’a été fourni</string> <string name="stops_near_code">Arrêts à proximité de %1$s</string> <string name="vehicle_headsign_content_description">%1$s vers %2$s</string> <string name="title_about">A propos</string> <string name="website_button_description">Lien vers le site</string> <string name="use_online_feed">Utiliser le flux en ligne</string> - <string name="error_406">La version de l\'application est incompatible avec le serveur</string> + <string name="error_406">La version de l’application est incompatible avec le serveur</string> <string name="title_filter">Filtrer</string> <string name="cancel">Annuler</string> <string name="more">Plus</string> @@ -69,7 +69,7 @@Le véhicule est accessible pour les fauteuils roulants <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="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> @@ -85,25 +85,25 @@Choisir une ligne <string name="last_update">Dernière mise à jour : %1$s</string> <string name="title_servers">Serveurs</string> <string name="title_cities">Localités</string> - <string name="information_may_be_outdated">L\'information peut être obsolète</string> + <string name="information_may_be_outdated">L’information peut être obsolète</string> <string name="ok">OK</string> - <string name="no_location_message">L\'accès à la position est nécéssaire pour trouver les arrêts à proximité et afficher la position actuelle sur la carte. Les autres fonctions peuvent fonctionner sans cela. L\'accès peut être activé ou désactiver dans les paramètres du système à tout moment.</string> + <string name="no_location_message">L’accès à la position est nécéssaire pour trouver les arrêts à proximité et afficher la position actuelle sur la carte. Les autres fonctions peuvent fonctionner sans cela. L’accès peut être activé ou désactiver dans les paramètres du système à tout moment.</string> <string name="stop_stub_on_demand_in_zone">Arrêt à la demande dans la zone %1$s</string> <string name="stop_stub_in_zone">Arrêt dans la zone %1$s</string> <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 ; une fiche horaire dans votre poche.</string> - <string name="error_41">Cette localité n\'est pas couverte par le serveur</string> + <string name="error_41">Cette localité n’est pas couverte par le serveur</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="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="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) © 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_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> <string name="onboarding_simple_action">Choisir la localité</string> @@ -201,7 +201,7 @@%1$s yd <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="map_attribution"><![CDATA[© 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> @@ -225,9 +225,9 @@un <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_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="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> @@ -236,9 +236,9 @@Alertes <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_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="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> @@ -248,4 +248,4 @@Départ <string name="departure_arrived">Arrivé</string> <string name="departure_approximate">Départ approximatif</string> <string name="approximately">Approximativement</string> -</resources> \ No newline at end of file +</resources> diff --git a/fruchtfleisch/build.gradle.kts b/fruchtfleisch/build.gradle.kts index 43fb515fc848c87a101c325f986d0cc4e2de095d..46f31384bc4e95115c60fb43676853c364c0227e 100644 --- a/fruchtfleisch/build.gradle.kts +++ b/fruchtfleisch/build.gradle.kts @@ -8,8 +8,8 @@ kotlin("jvm") } dependencies { - testImplementation("org.junit.jupiter:junit-jupiter:5.11.4") - testImplementation("org.junit.jupiter:junit-jupiter:5.11.4") + testImplementation("org.junit.jupiter:junit-jupiter:5.12.0") + testImplementation("org.junit.jupiter:junit-jupiter:5.12.0") //implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.10") } diff --git a/metadata/en-US/changelogs/36.txt b/metadata/en-US/changelogs/36.txt new file mode 100644 index 0000000000000000000000000000000000000000..5d9b90e518374aa4790e7770deb1656621d7c0a9 --- /dev/null +++ b/metadata/en-US/changelogs/36.txt @@ -0,0 +1,2 @@ +* added travel planning based on Transitous +* added translations by Arkadiusz, ArnaudDvs, Jonah Brüchert, Kemal Oktay Aktoğan, Priit Jõerüüt, Xapitonov, தமிழ்நேரம்