Author: Adam <git@apiote.xyz>
error handling
%!v(PANIC=String method: strings: negative Repeat count)
diff --git a/app/src/main/java/ml/adamsprogs/bimba/api/Api.kt b/app/src/main/java/ml/adamsprogs/bimba/api/Api.kt index d4ef93183cd94fa5f9fc54d150ea130c42535c54..9003b635331206b7d7214cd7d2b8146607f47e52 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/api/Api.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/api/Api.kt @@ -14,7 +14,7 @@ data class Server(val host: String, val token: String, val feeds: String) data class Result(val stream: InputStream?, val error: Error?) -data class Error(val statusCode: Int, val stringResource: Int) +data class Error(val statusCode: Int, val stringResource: Int, val imageResource: Int) @Suppress("BlockingMethodInNonBlockingContext") suspend fun getFeeds(cm: ConnectivityManager, server: Server): Result { @@ -46,7 +46,7 @@ suspend fun rawRequest(url: URL, server: Server, cm: ConnectivityManager): Result { @Suppress("DEPRECATION") // fix_later(API_29, API_23) https://developer.android.com/reference/android/net/ConnectivityManager#getActiveNetwork() if (cm.activeNetworkInfo == null) { // todo check false-positives - return Result(null, Error(0, R.string.error_offline)) + return Result(null, Error(0, R.string.error_offline, R.drawable.error_net)) } return withContext(Dispatchers.IO) { val c = (url.openConnection() as HttpURLConnection).apply { @@ -56,23 +56,25 @@ try { if (c.responseCode == 200) { Result(c.inputStream, null) } else { - val string = when (c.responseCode) { - 400 -> R.string.error_400 - 401 -> R.string.error_401 - 403 -> R.string.error_403 - 404 -> R.string.error_404 // todo check if server returns 404 - 429 -> R.string.error_429 - 500 -> R.string.error_50x - 502 -> R.string.error_50x - 503 -> R.string.error_50x - 504 -> R.string.error_50x - else -> R.string.error_unknown + val (string, image) = when (c.responseCode) { + 400 -> Pair(R.string.error_400, R.drawable.error_app) + 401 -> Pair(R.string.error_401, R.drawable.error_sec) + 403 -> Pair(R.string.error_403, R.drawable.error_sec) + 404 -> Pair( + R.string.error_404, + R.drawable.error_search + ) // todo check if server returns 404 + 429 -> Pair(R.string.error_429, R.drawable.error_limit) + 500 -> Pair(R.string.error_50x, R.drawable.error_server) + 502 -> Pair(R.string.error_50x, R.drawable.error_server) + 503 -> Pair(R.string.error_50x, R.drawable.error_server) + 504 -> Pair(R.string.error_50x, R.drawable.error_server) + else -> Pair(R.string.error_unknown, R.drawable.error_other) } - Result(c.errorStream, Error(c.responseCode, string)) + Result(c.errorStream, Error(c.responseCode, string, image)) } } catch (e: IOException) { - // todo timeout, no Internet connection - Result(null, Error(0, R.string.error_connecting)) + Result(null, Error(0, R.string.error_connecting, R.drawable.error_server)) } } } diff --git a/app/src/main/java/ml/adamsprogs/bimba/departures/DeparturesActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/departures/DeparturesActivity.kt index 0e9e821e8aec10c6e835504ac36019f720980646..eb3ce1061c018ec3040fe7d9b95aaab3d109d4af 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/departures/DeparturesActivity.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/departures/DeparturesActivity.kt @@ -8,6 +8,7 @@ import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import android.view.View +import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.res.ResourcesCompat import androidx.core.view.WindowCompat import androidx.recyclerview.widget.LinearLayoutManager @@ -92,6 +93,7 @@ } if (departuresResult.error != null) { Log.e("Departures", "$departuresResult") Log.e("Departures", "$response") + showError(departuresResult.error) } else { updateItems((response as DeparturesSuccess)) } @@ -104,12 +106,39 @@ DeparturesResponse.unmarshal(stream) } } + private fun showError(error: Error) { + binding.departuresProgress.visibility = View.GONE + binding.departuresRecycler.visibility = View.GONE + binding.errorImage.visibility = View.VISIBLE + binding.errorText.visibility = View.VISIBLE + + binding.errorText.text = getString(error.stringResource) + binding.errorImage.setImageDrawable(AppCompatResources.getDrawable(this, error.imageResource)) + } + private fun updateItems(response: DeparturesSuccess) { binding.departuresProgress.visibility = View.GONE - binding.departuresRecycler.visibility = View.VISIBLE adapter.update(response.departures) binding.collapsingLayout.apply { title = response.stop.name + } + if (response.departures.isEmpty()) { + binding.errorImage.visibility = View.VISIBLE + binding.errorText.visibility = View.VISIBLE + binding.departuresRecycler.visibility = View.GONE + + binding.errorText.text = getString(R.string.no_departures) + binding.errorImage.setImageDrawable( + AppCompatResources.getDrawable( + this, + R.drawable.error_search + ) + ) + } else { + binding.departuresOverlay.visibility = View.GONE + binding.errorImage.visibility = View.GONE + binding.errorText.visibility = View.GONE + binding.departuresRecycler.visibility = View.VISIBLE } // todo alerts // todo stop info diff --git a/app/src/main/java/ml/adamsprogs/bimba/search/ResultsActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/search/ResultsActivity.kt index 3ce675b57f7b328e7c503d4f54ebdd41533c1163..038e11559ff0acdd6eaa2158c1aa1cee2a818636 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/search/ResultsActivity.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/search/ResultsActivity.kt @@ -9,14 +9,19 @@ import android.location.LocationListener import android.location.LocationManager import android.net.ConnectivityManager import android.os.Bundle +import android.os.Handler +import android.os.Looper import android.util.Log import android.view.View import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.content.res.AppCompatResources import androidx.core.view.WindowCompat import androidx.recyclerview.widget.LinearLayoutManager import com.google.openlocationcode.OpenLocationCode import kotlinx.coroutines.* import ml.adamsprogs.bimba.departures.DeparturesActivity +import kotlinx.coroutines.Runnable +import ml.adamsprogs.bimba.R import ml.adamsprogs.bimba.api.* import ml.adamsprogs.bimba.databinding.ActivityResultsBinding import java.io.InputStream @@ -31,6 +36,9 @@ private val binding get() = _binding!! private lateinit var adapter: BimbaResultsAdapter private lateinit var preferences: SharedPreferences + + private val handler = Handler(Looper.getMainLooper()) + private var runnable = Runnable {} override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -85,12 +93,17 @@ val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 5000, 10f, this ) - // todo(error-handling) timeout + handler.removeCallbacks(runnable) + runnable = Runnable { + showError(Error(0, R.string.error_gps, R.drawable.error_gps)) + } + handler.postDelayed(runnable, 60 * 1000) locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) ?.let { onLocationChanged(it) } } override fun onLocationChanged(location: Location) { + handler.removeCallbacks(runnable) val code = OpenLocationCode.encode(location.latitude, location.longitude) val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager locationManager.removeUpdates(this) @@ -121,7 +134,7 @@ } if (itemsResult.error != null) { Log.e("Results.query", "$itemsResult") Log.e("Results.query", "$response") - // todo(error-handling) show empty state + showError(itemsResult.error) } else { updateItems((response as ItemsSuccess).items) } @@ -140,17 +153,44 @@ } if (itemsResult.error != null) { Log.e("Results.location", "$itemsResult") Log.e("Results.location", "$response") - // todo(error-handling) show empty state + showError(itemsResult.error) } else { updateItems((response as ItemsSuccess).items) } } } + private fun showError(error: Error) { + binding.resultsProgress.visibility = View.GONE + binding.resultsRecycler.visibility = View.GONE + binding.errorImage.visibility = View.VISIBLE + binding.errorText.visibility = View.VISIBLE + + binding.errorText.text = getString(error.stringResource) + binding.errorImage.setImageDrawable(AppCompatResources.getDrawable(this, error.imageResource)) + } + private fun updateItems(items: List<Item>) { binding.resultsProgress.visibility = View.GONE - binding.resultsRecycler.visibility = View.VISIBLE adapter.update(items) + if (items.isEmpty()) { + binding.errorImage.visibility = View.VISIBLE + binding.errorText.visibility = View.VISIBLE + binding.resultsRecycler.visibility = View.GONE + + binding.errorText.text = getString(R.string.error_404) + binding.errorImage.setImageDrawable( + AppCompatResources.getDrawable( + this, + R.drawable.error_search + ) + ) + } else { + binding.resultsOverlay.visibility = View.GONE + binding.errorImage.visibility = View.GONE + binding.errorText.visibility = View.GONE + binding.resultsRecycler.visibility = View.VISIBLE + } } private suspend fun unmarshallItemResponse(stream: InputStream): ItemsResponse { diff --git a/app/src/main/res/drawable/error_app.xml b/app/src/main/res/drawable/error_app.xml new file mode 100644 index 0000000000000000000000000000000000000000..adaa37eb80f7276f9ac19caec2c1c8c9fca932de --- /dev/null +++ b/app/src/main/res/drawable/error_app.xml @@ -0,0 +1,5 @@ +<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="M18,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM15.5,12c0,-1.38 1.12,-2.5 2.5,-2.5 0.42,0 0.8,0.11 1.15,0.29l-3.36,3.36c-0.18,-0.35 -0.29,-0.73 -0.29,-1.15zM18,14.5c-0.42,0 -0.8,-0.11 -1.15,-0.29l3.36,-3.36c0.18,0.35 0.29,0.73 0.29,1.15 0,1.38 -1.12,2.5 -2.5,2.5zM17,18L7,18L7,6h10v1h2L19,3c0,-1.1 -0.9,-2 -2,-2L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2v-4h-2v1z"/> +</vector> diff --git a/app/src/main/res/drawable/error_gps.xml b/app/src/main/res/drawable/error_gps.xml new file mode 100644 index 0000000000000000000000000000000000000000..d83a38e79abe3672f08f1e811d88e184ddadc1e4 --- /dev/null +++ b/app/src/main/res/drawable/error_gps.xml @@ -0,0 +1,5 @@ +<vector android:height="24dp" android:tint="?attr/colorOnSurface" + android:viewportHeight="24" android:viewportWidth="24" + android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="@android:color/white" android:pathData="M20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06c-1.13,0.12 -2.19,0.46 -3.16,0.97l1.5,1.5C10.16,5.19 11.06,5 12,5c3.87,0 7,3.13 7,7 0,0.94 -0.19,1.84 -0.52,2.65l1.5,1.5c0.5,-0.96 0.84,-2.02 0.97,-3.15L23,13v-2h-2.06zM3,4.27l2.04,2.04C3.97,7.62 3.25,9.23 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c1.77,-0.2 3.38,-0.91 4.69,-1.98L19.73,21 21,19.73 4.27,3 3,4.27zM16.27,17.54C15.09,18.45 13.61,19 12,19c-3.87,0 -7,-3.13 -7,-7 0,-1.61 0.55,-3.09 1.46,-4.27l9.81,9.81z"/> +</vector> diff --git a/app/src/main/res/drawable/error_limit.xml b/app/src/main/res/drawable/error_limit.xml new file mode 100644 index 0000000000000000000000000000000000000000..03344fd1addcf979b8cdc1c4cb33cf699add2401 --- /dev/null +++ b/app/src/main/res/drawable/error_limit.xml @@ -0,0 +1,5 @@ +<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="M23,5.5V20c0,2.2 -1.8,4 -4,4h-7.3c-1.08,0 -2.1,-0.43 -2.85,-1.19L1,14.83c0,0 1.26,-1.23 1.3,-1.25c0.22,-0.19 0.49,-0.29 0.79,-0.29c0.22,0 0.42,0.06 0.6,0.16C3.73,13.46 8,15.91 8,15.91V4c0,-0.83 0.67,-1.5 1.5,-1.5S11,3.17 11,4v7h1V1.5C12,0.67 12.67,0 13.5,0S15,0.67 15,1.5V11h1V2.5C16,1.67 16.67,1 17.5,1S19,1.67 19,2.5V11h1V5.5C20,4.67 20.67,4 21.5,4S23,4.67 23,5.5z"/> +</vector> diff --git a/app/src/main/res/drawable/error_net.xml b/app/src/main/res/drawable/error_net.xml new file mode 100644 index 0000000000000000000000000000000000000000..dde6900202fa85a63b608e96248a012b815f8d1d --- /dev/null +++ b/app/src/main/res/drawable/error_net.xml @@ -0,0 +1,5 @@ +<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="M23.64,7c-0.45,-0.34 -4.93,-4 -11.64,-4 -1.5,0 -2.89,0.19 -4.15,0.48L18.18,13.8 23.64,7zM17.04,15.22L3.27,1.44 2,2.72l2.05,2.06C1.91,5.76 0.59,6.82 0.36,7l11.63,14.49 0.01,0.01 0.01,-0.01 3.9,-4.86 3.32,3.32 1.27,-1.27 -3.46,-3.46z"/> +</vector> diff --git a/app/src/main/res/drawable/error_other.xml b/app/src/main/res/drawable/error_other.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4c7fcdbf80efb3e3fc7daebf5cf6634412ca8b0 --- /dev/null +++ b/app/src/main/res/drawable/error_other.xml @@ -0,0 +1,5 @@ +<vector android:height="24dp" android:tint="?attr/colorOnSurface" + android:viewportHeight="24" android:viewportWidth="24" + android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-2h2v2zM13,13h-2L11,7h2v6z"/> +</vector> diff --git a/app/src/main/res/drawable/error_search.xml b/app/src/main/res/drawable/error_search.xml new file mode 100644 index 0000000000000000000000000000000000000000..66931d11070e03fd2d2f20c26700a0d77a45c17a --- /dev/null +++ b/app/src/main/res/drawable/error_search.xml @@ -0,0 +1,6 @@ +<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="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5C16,5.91 13.09,3 9.5,3C6.08,3 3.28,5.64 3.03,9h2.02C5.3,6.75 7.18,5 9.5,5C11.99,5 14,7.01 14,9.5S11.99,14 9.5,14c-0.17,0 -0.33,-0.03 -0.5,-0.05v2.02C9.17,15.99 9.33,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57L14,14.71v0.79l5,4.99L20.49,19L15.5,14z"/> + <path android:fillColor="@android:color/white" android:pathData="M6.47,10.82l-2.47,2.47l-2.47,-2.47l-0.71,0.71l2.47,2.47l-2.47,2.47l0.71,0.71l2.47,-2.47l2.47,2.47l0.71,-0.71l-2.47,-2.47l2.47,-2.47z"/> +</vector> diff --git a/app/src/main/res/drawable/error_sec.xml b/app/src/main/res/drawable/error_sec.xml new file mode 100644 index 0000000000000000000000000000000000000000..e6842fb025a6ca3102a2f1da225a2e0048ca2f66 --- /dev/null +++ b/app/src/main/res/drawable/error_sec.xml @@ -0,0 +1,5 @@ +<vector android:height="24dp" android:tint="?attr/colorOnSurface" + android:viewportHeight="24" android:viewportWidth="24" + android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="@android:color/white" android:pathData="M12,2L4,5v6.09c0,5.05 3.41,9.76 8,10.91c4.59,-1.15 8,-5.86 8,-10.91V5L12,2zM15.5,14.09l-1.41,1.41L12,13.42L9.91,15.5L8.5,14.09L10.59,12L8.5,9.91L9.91,8.5L12,10.59l2.09,-2.09l1.41,1.41L13.42,12L15.5,14.09z"/> +</vector> diff --git a/app/src/main/res/drawable/error_server.xml b/app/src/main/res/drawable/error_server.xml new file mode 100644 index 0000000000000000000000000000000000000000..6fddd7413b943415429acce7c9d329dd06e2c98b --- /dev/null +++ b/app/src/main/res/drawable/error_server.xml @@ -0,0 +1,5 @@ +<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="M11,8.17L6.49,3.66C8.07,2.61 9.96,2 12,2c5.52,0 10,4.48 10,10c0,2.04 -0.61,3.93 -1.66,5.51l-1.46,-1.46C19.59,14.87 20,13.48 20,12c0,-3.35 -2.07,-6.22 -5,-7.41V5c0,1.1 -0.9,2 -2,2h-2V8.17zM21.19,21.19l-1.41,1.41l-2.27,-2.27C15.93,21.39 14.04,22 12,22C6.48,22 2,17.52 2,12c0,-2.04 0.61,-3.93 1.66,-5.51L1.39,4.22l1.41,-1.41L21.19,21.19zM11,18c-1.1,0 -2,-0.9 -2,-2v-1l-4.79,-4.79C4.08,10.79 4,11.38 4,12c0,4.08 3.05,7.44 7,7.93V18z"/> +</vector> diff --git a/app/src/main/res/layout/activity_departures.xml b/app/src/main/res/layout/activity_departures.xml index 914ead5d00e7339ebd0f746d5ae2f084e4d9697a..552d23dd735a7ccaefdba0088b845182b3d6fda6 100644 --- a/app/src/main/res/layout/activity_departures.xml +++ b/app/src/main/res/layout/activity_departures.xml @@ -1,15 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.constraintlayout.widget.ConstraintLayout - android:id="@+id/departures_progress" + android:id="@+id/departures_overlay" android:layout_width="match_parent" android:layout_height="match_parent"> <ProgressBar + android:id="@+id/departures_progress" style="?android:attr/progressBarStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -17,6 +19,33 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + <ImageView + android:id="@+id/errorImage" + android:layout_width="92dp" + android:layout_height="92dp" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:ignore="ContentDescription" + tools:src="@drawable/error_net" /> + + <TextView + android:id="@+id/errorText" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="8dp" + android:layout_marginEnd="16dp" + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" + android:visibility="gone" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/errorImage" + tools:text="No connection" /> </androidx.constraintlayout.widget.ConstraintLayout> <com.google.android.material.appbar.AppBarLayout diff --git a/app/src/main/res/layout/activity_results.xml b/app/src/main/res/layout/activity_results.xml index f390da570b37b1b1deb63b036506b34be05d63b6..544c223c2396559b92f1042c1f6832ab9cd69e43 100644 --- a/app/src/main/res/layout/activity_results.xml +++ b/app/src/main/res/layout/activity_results.xml @@ -1,15 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.constraintlayout.widget.ConstraintLayout - android:id="@+id/results_progress" + android:id="@+id/results_overlay" android:layout_width="match_parent" android:layout_height="match_parent"> <ProgressBar + android:id="@+id/results_progress" style="?android:attr/progressBarStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -17,6 +19,34 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + <ImageView + android:id="@+id/errorImage" + android:layout_width="92dp" + android:layout_height="92dp" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:ignore="ContentDescription" + tools:src="@drawable/error_net" /> + + <TextView + android:id="@+id/errorText" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="8dp" + android:layout_marginEnd="16dp" + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" + android:visibility="gone" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/errorImage" + tools:text="No connection" /> + </androidx.constraintlayout.widget.ConstraintLayout> <com.google.android.material.appbar.AppBarLayout diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 906554c8b1e3a54af2cfe5069b4641644dff11d8..51b4adeb82ec6ebadf9d62aada03881473d907d9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -20,4 +20,6 @@There was an error on the sever. Try again later <string name="error_unknown">Unknown error happened</string> <string name="error_connecting">Error connecting to the server. Try again later</string> <string name="error_offline">You are offline. Connect to the Internet</string> <!-- send a bug report to bimba@git.apiote.xyz, details are: url=$URL, response=$response --> + <string name="error_gps">Cannot obtain location</string> + <string name="no_departures">No departures</string> </resources> \ No newline at end of file