Handling map loading error in timeline

This commit is contained in:
Maxime NATUREL 2022-08-01 14:45:08 +02:00
parent e0e06c6ac8
commit 6972622bc6
7 changed files with 94 additions and 34 deletions

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MapLoadingErrorView">
<attr name="mapErrorDescription" format="string" />
</declare-styleable>
</resources>

View file

@ -36,6 +36,8 @@ import im.vector.app.core.utils.DimensionConverter
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
import im.vector.app.features.home.room.detail.timeline.style.granularRoundedCorners
import im.vector.app.features.location.MapLoadingErrorView
import im.vector.app.features.location.MapLoadingErrorViewState
abstract class AbsMessageLocationItem<H : AbsMessageLocationItem.Holder>(
@LayoutRes layoutId: Int = R.layout.item_timeline_event_base
@ -86,8 +88,10 @@ abstract class AbsMessageLocationItem<H : AbsMessageLocationItem.Holder>(
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
holder.staticMapPinImageView.setImageResource(R.drawable.ic_location_pin_failed)
holder.staticMapErrorTextView.isVisible = true
holder.staticMapPinImageView.setImageDrawable(null)
holder.staticMapLoadingErrorView.isVisible = true
val mapErrorViewState = MapLoadingErrorViewState(imageCornerTransformation)
holder.staticMapLoadingErrorView.render(mapErrorViewState)
holder.staticMapCopyrightTextView.isVisible = false
return false
}
@ -103,7 +107,7 @@ abstract class AbsMessageLocationItem<H : AbsMessageLocationItem.Holder>(
// we are not using Glide since it does not display it correctly when there is no user photo
holder.staticMapPinImageView.setImageDrawable(pinDrawable)
}
holder.staticMapErrorTextView.isVisible = false
holder.staticMapLoadingErrorView.isVisible = false
holder.staticMapCopyrightTextView.isVisible = true
return false
}
@ -115,7 +119,7 @@ abstract class AbsMessageLocationItem<H : AbsMessageLocationItem.Holder>(
abstract class Holder(@IdRes stubId: Int) : AbsMessageItem.Holder(stubId) {
val staticMapImageView by bind<ImageView>(R.id.staticMapImageView)
val staticMapPinImageView by bind<ImageView>(R.id.staticMapPinImageView)
val staticMapErrorTextView by bind<TextView>(R.id.staticMapErrorTextView)
val staticMapLoadingErrorView by bind<MapLoadingErrorView>(R.id.staticMapLoadingError)
val staticMapCopyrightTextView by bind<TextView>(R.id.staticMapCopyrightTextView)
}
}

View file

@ -17,10 +17,16 @@
package im.vector.app.features.location
import android.content.Context
import android.content.res.TypedArray
import android.graphics.drawable.ColorDrawable
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.res.use
import im.vector.app.R
import im.vector.app.core.glide.GlideApp
import im.vector.app.databinding.ViewMapLoadingErrorBinding
import im.vector.app.features.themes.ThemeUtils
/**
* Custom view to display an error when map fails to load.
@ -29,10 +35,35 @@ class MapLoadingErrorView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
private val binding = ViewMapLoadingErrorBinding.inflate(
LayoutInflater.from(context),
this
)
init {
ViewMapLoadingErrorBinding.inflate(
LayoutInflater.from(context),
this
)
context.obtainStyledAttributes(
attrs,
R.styleable.MapLoadingErrorView,
0,
0
).use {
setErrorDescription(it)
}
}
private fun setErrorDescription(typedArray: TypedArray) {
val description = typedArray.getString(R.styleable.MapLoadingErrorView_mapErrorDescription)
if(description.isNullOrEmpty()) {
binding.mapLoadingErrorDescription.setText(R.string.location_share_loading_map_error)
} else {
binding.mapLoadingErrorDescription.text = description
}
}
fun render(mapLoadingErrorViewState: MapLoadingErrorViewState) {
GlideApp.with(binding.mapLoadingErrorBackground)
.load(ColorDrawable(ThemeUtils.getColor(context, R.attr.vctr_system)))
.transform(mapLoadingErrorViewState.backgroundTransformation)
.into(binding.mapLoadingErrorBackground)
}
}

View file

@ -0,0 +1,21 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.location
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
data class MapLoadingErrorViewState(val backgroundTransformation: BitmapTransformation)

View file

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="70dp"
android:height="70dp"
android:viewportWidth="70"
android:viewportHeight="70">
<path
android:pathData="M34.9997,5.8335C23.7122,5.8335 14.583,15.2112 14.583,26.8059C14.583,39.2995 27.4747,56.5269 32.783,63.0882C33.9497,64.5264 36.0788,64.5264 37.2455,63.0882C42.5247,56.5269 55.4163,39.2995 55.4163,26.8059C55.4163,15.2112 46.2872,5.8335 34.9997,5.8335ZM34.9997,34.2961C30.9747,34.2961 27.708,30.9405 27.708,26.8059C27.708,22.6714 30.9747,19.3158 34.9997,19.3158C39.0247,19.3158 42.2913,22.6714 42.2913,26.8059C42.2913,30.9405 39.0247,34.2961 34.9997,34.2961Z"
android:fillColor="#C1C6CD"/>
</vector>

View file

@ -29,21 +29,16 @@
app:layout_constraintTop_toTopOf="@id/staticMapImageView"
app:layout_constraintVertical_bias="1.0" />
<TextView
android:id="@+id/staticMapErrorTextView"
style="@style/Widget.Vector.TextView.Subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginTop="16dp"
android:layout_marginBottom="54dp"
android:text="@string/location_timeline_failed_to_load_map"
android:textColor="?vctr_content_tertiary"
<im.vector.app.features.location.MapLoadingErrorView
android:id="@+id/staticMapLoadingError"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="@id/staticMapPinImageView"
app:layout_constraintStart_toStartOf="@id/staticMapPinImageView"
app:layout_constraintTop_toBottomOf="@id/staticMapPinImageView"
tools:visibility="visible" />
app:layout_constraintBottom_toTopOf="@id/locationLiveRunningBanner"
app:layout_constraintEnd_toEndOf="@id/staticMapImageView"
app:layout_constraintStart_toStartOf="@id/staticMapImageView"
app:layout_constraintTop_toTopOf="@id/staticMapImageView"
app:mapErrorDescription="@string/location_timeline_failed_to_load_map" />
<im.vector.app.features.location.live.LiveLocationRunningBannerView
android:id="@+id/liveLocationRunningBanner"

View file

@ -6,11 +6,21 @@
android:layout_height="match_parent"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
<ImageView
android:id="@+id/mapLoadingErrorBackground"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="?vctr_system"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<androidx.constraintlayout.helper.widget.Flow
android:id="@+id/mapLoadingErrorContainer"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="?vctr_system"
android:orientation="vertical"
app:constraint_referenced_ids="mapLoadingErrorIcon,mapLoadingErrorDescription"
app:flow_verticalGap="12dp"
@ -24,8 +34,8 @@
android:id="@+id/mapLoadingErrorIcon"
android:layout_width="28dp"
android:layout_height="28dp"
android:contentDescription="@string/a11y_location_share_option_pinned_icon"
android:src="@drawable/ic_warning_badge" />
android:src="@drawable/ic_warning_badge"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/mapLoadingErrorDescription"