Handling map loading error in timeline
This commit is contained in:
		
							parent
							
								
									e0e06c6ac8
								
							
						
					
					
						commit
						6972622bc6
					
				| @ -0,0 +1,8 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <resources> | ||||||
|  | 
 | ||||||
|  |     <declare-styleable name="MapLoadingErrorView"> | ||||||
|  |         <attr name="mapErrorDescription" format="string" /> | ||||||
|  |     </declare-styleable> | ||||||
|  | 
 | ||||||
|  | </resources> | ||||||
| @ -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.helper.LocationPinProvider | ||||||
| import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout | 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.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>( | abstract class AbsMessageLocationItem<H : AbsMessageLocationItem.Holder>( | ||||||
|         @LayoutRes layoutId: Int = R.layout.item_timeline_event_base |         @LayoutRes layoutId: Int = R.layout.item_timeline_event_base | ||||||
| @ -86,8 +88,10 @@ abstract class AbsMessageLocationItem<H : AbsMessageLocationItem.Holder>( | |||||||
|                             target: Target<Drawable>?, |                             target: Target<Drawable>?, | ||||||
|                             isFirstResource: Boolean |                             isFirstResource: Boolean | ||||||
|                     ): Boolean { |                     ): Boolean { | ||||||
|                         holder.staticMapPinImageView.setImageResource(R.drawable.ic_location_pin_failed) |                         holder.staticMapPinImageView.setImageDrawable(null) | ||||||
|                         holder.staticMapErrorTextView.isVisible = true |                         holder.staticMapLoadingErrorView.isVisible = true | ||||||
|  |                         val mapErrorViewState = MapLoadingErrorViewState(imageCornerTransformation) | ||||||
|  |                         holder.staticMapLoadingErrorView.render(mapErrorViewState) | ||||||
|                         holder.staticMapCopyrightTextView.isVisible = false |                         holder.staticMapCopyrightTextView.isVisible = false | ||||||
|                         return 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 |                             // we are not using Glide since it does not display it correctly when there is no user photo | ||||||
|                             holder.staticMapPinImageView.setImageDrawable(pinDrawable) |                             holder.staticMapPinImageView.setImageDrawable(pinDrawable) | ||||||
|                         } |                         } | ||||||
|                         holder.staticMapErrorTextView.isVisible = false |                         holder.staticMapLoadingErrorView.isVisible = false | ||||||
|                         holder.staticMapCopyrightTextView.isVisible = true |                         holder.staticMapCopyrightTextView.isVisible = true | ||||||
|                         return false |                         return false | ||||||
|                     } |                     } | ||||||
| @ -115,7 +119,7 @@ abstract class AbsMessageLocationItem<H : AbsMessageLocationItem.Holder>( | |||||||
|     abstract class Holder(@IdRes stubId: Int) : AbsMessageItem.Holder(stubId) { |     abstract class Holder(@IdRes stubId: Int) : AbsMessageItem.Holder(stubId) { | ||||||
|         val staticMapImageView by bind<ImageView>(R.id.staticMapImageView) |         val staticMapImageView by bind<ImageView>(R.id.staticMapImageView) | ||||||
|         val staticMapPinImageView by bind<ImageView>(R.id.staticMapPinImageView) |         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) |         val staticMapCopyrightTextView by bind<TextView>(R.id.staticMapCopyrightTextView) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -17,10 +17,16 @@ | |||||||
| package im.vector.app.features.location | package im.vector.app.features.location | ||||||
| 
 | 
 | ||||||
| import android.content.Context | import android.content.Context | ||||||
|  | import android.content.res.TypedArray | ||||||
|  | import android.graphics.drawable.ColorDrawable | ||||||
| import android.util.AttributeSet | import android.util.AttributeSet | ||||||
| import android.view.LayoutInflater | import android.view.LayoutInflater | ||||||
| import androidx.constraintlayout.widget.ConstraintLayout | 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.databinding.ViewMapLoadingErrorBinding | ||||||
|  | import im.vector.app.features.themes.ThemeUtils | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Custom view to display an error when map fails to load. |  * 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 |         context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 | ||||||
| ) : ConstraintLayout(context, attrs, defStyleAttr) { | ) : ConstraintLayout(context, attrs, defStyleAttr) { | ||||||
| 
 | 
 | ||||||
|  |     private val binding = ViewMapLoadingErrorBinding.inflate( | ||||||
|  |             LayoutInflater.from(context), | ||||||
|  |             this | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|     init { |     init { | ||||||
|         ViewMapLoadingErrorBinding.inflate( |         context.obtainStyledAttributes( | ||||||
|                 LayoutInflater.from(context), |                 attrs, | ||||||
|                 this |                 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) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -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) | ||||||
| @ -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> |  | ||||||
| @ -29,21 +29,16 @@ | |||||||
|         app:layout_constraintTop_toTopOf="@id/staticMapImageView" |         app:layout_constraintTop_toTopOf="@id/staticMapImageView" | ||||||
|         app:layout_constraintVertical_bias="1.0" /> |         app:layout_constraintVertical_bias="1.0" /> | ||||||
| 
 | 
 | ||||||
|     <TextView |     <im.vector.app.features.location.MapLoadingErrorView | ||||||
|         android:id="@+id/staticMapErrorTextView" |         android:id="@+id/staticMapLoadingError" | ||||||
|         style="@style/Widget.Vector.TextView.Subtitle" |         android:layout_width="0dp" | ||||||
|         android:layout_width="wrap_content" |         android:layout_height="0dp" | ||||||
|         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" |  | ||||||
|         android:visibility="gone" |         android:visibility="gone" | ||||||
|         app:layout_constraintEnd_toEndOf="@id/staticMapPinImageView" |         app:layout_constraintBottom_toTopOf="@id/locationLiveRunningBanner" | ||||||
|         app:layout_constraintStart_toStartOf="@id/staticMapPinImageView" |         app:layout_constraintEnd_toEndOf="@id/staticMapImageView" | ||||||
|         app:layout_constraintTop_toBottomOf="@id/staticMapPinImageView" |         app:layout_constraintStart_toStartOf="@id/staticMapImageView" | ||||||
|         tools:visibility="visible" /> |         app:layout_constraintTop_toTopOf="@id/staticMapImageView" | ||||||
|  |         app:mapErrorDescription="@string/location_timeline_failed_to_load_map" /> | ||||||
| 
 | 
 | ||||||
|     <im.vector.app.features.location.live.LiveLocationRunningBannerView |     <im.vector.app.features.location.live.LiveLocationRunningBannerView | ||||||
|         android:id="@+id/liveLocationRunningBanner" |         android:id="@+id/liveLocationRunningBanner" | ||||||
|  | |||||||
| @ -6,11 +6,21 @@ | |||||||
|     android:layout_height="match_parent" |     android:layout_height="match_parent" | ||||||
|     tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> |     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 |     <androidx.constraintlayout.helper.widget.Flow | ||||||
|         android:id="@+id/mapLoadingErrorContainer" |         android:id="@+id/mapLoadingErrorContainer" | ||||||
|         android:layout_width="0dp" |         android:layout_width="0dp" | ||||||
|         android:layout_height="0dp" |         android:layout_height="0dp" | ||||||
|         android:background="?vctr_system" |  | ||||||
|         android:orientation="vertical" |         android:orientation="vertical" | ||||||
|         app:constraint_referenced_ids="mapLoadingErrorIcon,mapLoadingErrorDescription" |         app:constraint_referenced_ids="mapLoadingErrorIcon,mapLoadingErrorDescription" | ||||||
|         app:flow_verticalGap="12dp" |         app:flow_verticalGap="12dp" | ||||||
| @ -24,8 +34,8 @@ | |||||||
|         android:id="@+id/mapLoadingErrorIcon" |         android:id="@+id/mapLoadingErrorIcon" | ||||||
|         android:layout_width="28dp" |         android:layout_width="28dp" | ||||||
|         android:layout_height="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 |     <TextView | ||||||
|         android:id="@+id/mapLoadingErrorDescription" |         android:id="@+id/mapLoadingErrorDescription" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user