mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 23:32:41 +00:00
Merge pull request #6499 from vector-im/steve/6493_lls_tile_server_error
Location sharing: Render fallback UI when tile server unavailable (PSG-606)
This commit is contained in:
commit
c9e916b909
15 changed files with 267 additions and 39 deletions
15
Riot/Assets/Images.xcassets/Room/Location/location_map_error.imageset/Contents.json
vendored
Normal file
15
Riot/Assets/Images.xcassets/Room/Location/location_map_error.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "location_map_error.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "original"
|
||||
}
|
||||
}
|
3
Riot/Assets/Images.xcassets/Room/Location/location_map_error.imageset/location_map_error.svg
vendored
Normal file
3
Riot/Assets/Images.xcassets/Room/Location/location_map_error.imageset/location_map_error.svg
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.5001 29.3327C23.8639 29.3327 29.8334 23.3631 29.8334 15.9993C29.8334 8.63555 23.8639 2.66602 16.5001 2.66602C9.13628 2.66602 3.16675 8.63555 3.16675 15.9993C3.16675 23.3631 9.13628 29.3327 16.5001 29.3327ZM14.3976 9.35707C14.2945 8.18144 15.1608 7.15019 16.3364 7.06769C17.4914 6.98519 18.5226 7.85144 18.6464 9.02707V9.35707L17.9864 17.6071C17.9245 18.3702 17.2851 18.9477 16.522 18.9477H16.3983C15.6764 18.8858 15.1195 18.3289 15.0576 17.6071L14.3976 9.35707ZM18.3154 22.9905C18.3154 23.9929 17.5028 24.8055 16.5004 24.8055C15.498 24.8055 14.6854 23.9929 14.6854 22.9905C14.6854 21.9881 15.498 21.1755 16.5004 21.1755C17.5028 21.1755 18.3154 21.9881 18.3154 22.9905Z" fill="#FF4B55"/>
|
||||
</svg>
|
After Width: | Height: | Size: 843 B |
|
@ -2279,6 +2279,7 @@ To enable access, tap Settings> Location and select Always";
|
|||
"location_sharing_allow_background_location_validate_action" = "Settings";
|
||||
"location_sharing_allow_background_location_cancel_action" = "Not now";
|
||||
"location_sharing_map_credits_title" = "© Copyright";
|
||||
"location_sharing_map_loading_error" = "Unable to load map\nThis homeserver is not configured to display maps";
|
||||
|
||||
// MARK: Live location sharing
|
||||
|
||||
|
|
|
@ -105,6 +105,8 @@ internal class Asset: NSObject {
|
|||
internal static let encryptionWarning = ImageAsset(name: "encryption_warning")
|
||||
internal static let favouritesEmptyScreenArtwork = ImageAsset(name: "favourites_empty_screen_artwork")
|
||||
internal static let favouritesEmptyScreenArtworkDark = ImageAsset(name: "favourites_empty_screen_artwork_dark")
|
||||
internal static let allChatRecents = ImageAsset(name: "all_chat_recents")
|
||||
internal static let allChatUnreads = ImageAsset(name: "all_chat_unreads")
|
||||
internal static let roomActionDirectChat = ImageAsset(name: "room_action_direct_chat")
|
||||
internal static let roomActionFavourite = ImageAsset(name: "room_action_favourite")
|
||||
internal static let roomActionLeave = ImageAsset(name: "room_action_leave")
|
||||
|
@ -112,6 +114,7 @@ internal class Asset: NSObject {
|
|||
internal static let roomActionNotificationMuted = ImageAsset(name: "room_action_notification_muted")
|
||||
internal static let roomActionPriorityHigh = ImageAsset(name: "room_action_priority_high")
|
||||
internal static let roomActionPriorityLow = ImageAsset(name: "room_action_priority_low")
|
||||
internal static let allChatEditLayout = ImageAsset(name: "all_chat_edit_layout")
|
||||
internal static let homeEmptyScreenArtwork = ImageAsset(name: "home_empty_screen_artwork")
|
||||
internal static let homeEmptyScreenArtworkDark = ImageAsset(name: "home_empty_screen_artwork_dark")
|
||||
internal static let homeFabCreateRoom = ImageAsset(name: "home_fab_create_room")
|
||||
|
@ -195,6 +198,7 @@ internal class Asset: NSObject {
|
|||
internal static let locationLiveCellIcon = ImageAsset(name: "location_live_cell_icon")
|
||||
internal static let locationLiveCellLoadingIcon = ImageAsset(name: "location_live_cell_loading_icon")
|
||||
internal static let locationLiveIcon = ImageAsset(name: "location_live_icon")
|
||||
internal static let locationMapError = ImageAsset(name: "location_map_error")
|
||||
internal static let locationMarkerIcon = ImageAsset(name: "location_marker_icon")
|
||||
internal static let locationPinIcon = ImageAsset(name: "location_pin_icon")
|
||||
internal static let locationShareIcon = ImageAsset(name: "location_share_icon")
|
||||
|
|
|
@ -3179,6 +3179,10 @@ public class VectorL10n: NSObject {
|
|||
public static var locationSharingMapCreditsTitle: String {
|
||||
return VectorL10n.tr("Vector", "location_sharing_map_credits_title")
|
||||
}
|
||||
/// Unable to load map\nThis homeserver is not configured to display maps
|
||||
public static var locationSharingMapLoadingError: String {
|
||||
return VectorL10n.tr("Vector", "location_sharing_map_loading_error")
|
||||
}
|
||||
/// Open in Apple Maps
|
||||
public static var locationSharingOpenAppleMaps: String {
|
||||
return VectorL10n.tr("Vector", "location_sharing_open_apple_maps")
|
||||
|
|
|
@ -104,7 +104,19 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
|||
@IBOutlet private var rightButton: UIButton!
|
||||
@IBOutlet private var activityIndicatorView: UIActivityIndicatorView!
|
||||
|
||||
@IBOutlet private var mapLoadingErrorContainerView: UIView!
|
||||
@IBOutlet private var mapLoadingErrorImageView: UIImageView!
|
||||
@IBOutlet private var mapLoadingErrorMessageLabel: UILabel!
|
||||
|
||||
private var mapView: MGLMapView!
|
||||
|
||||
private var isMapViewLoadingFailed: Bool = false {
|
||||
didSet {
|
||||
if oldValue != isMapViewLoadingFailed {
|
||||
self.mapViewLoadingStateDidChange()
|
||||
}
|
||||
}
|
||||
}
|
||||
private var annotationView: LocationMarkerView?
|
||||
private static var usernameColorGenerator = UserNameColorGenerator()
|
||||
private var theme: Theme!
|
||||
|
@ -157,16 +169,37 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
|||
layer.borderWidth = Constants.cellBorderRadius
|
||||
layer.cornerRadius = Constants.cellCornerRadius
|
||||
|
||||
mapLoadingErrorContainerView.isHidden = true
|
||||
mapLoadingErrorImageView.image = Asset.Images.locationMapError.image
|
||||
mapLoadingErrorMessageLabel.text = VectorL10n.locationSharingMapLoadingError
|
||||
|
||||
theme = ThemeService.shared().theme
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func resetMapViewLoadingState() {
|
||||
self.isMapViewLoadingFailed = false
|
||||
}
|
||||
|
||||
private func mapViewLoadingStateDidChange() {
|
||||
|
||||
if mapView.isHidden == false && self.isMapViewLoadingFailed {
|
||||
mapLoadingErrorContainerView.isHidden = false
|
||||
mapView.isHidden = true
|
||||
attributionLabel.isHidden = true
|
||||
} else {
|
||||
mapLoadingErrorContainerView.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
private func displayLocation(_ location: CLLocationCoordinate2D?,
|
||||
userAvatarData: AvatarViewData? = nil,
|
||||
mapStyleURL: URL,
|
||||
bannerViewData: TimelineLiveLocationViewData? = nil) {
|
||||
|
||||
resetMapViewLoadingState()
|
||||
|
||||
if let location = location {
|
||||
mapView.isHidden = false
|
||||
mapView.styleURL = mapStyleURL
|
||||
|
@ -350,6 +383,9 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
|||
self.theme = theme
|
||||
placeholderIcon = ThemeService.shared().isCurrentThemeDark() ? Asset.Images.locationLiveCellEndedDarkIcon.image : Asset.Images.locationLiveCellEndedLightIcon.image
|
||||
placeholderBackgroundImage = ThemeService.shared().isCurrentThemeDark() ? Asset.Images.locationBackgroundDarkImage.image : Asset.Images.locationBackgroundLightImage.image
|
||||
|
||||
mapLoadingErrorContainerView.backgroundColor = theme.colors.system
|
||||
mapLoadingErrorMessageLabel.textColor = theme.colors.primaryContent
|
||||
}
|
||||
|
||||
// MARK: - MGLMapViewDelegate
|
||||
|
@ -358,6 +394,17 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
|||
return annotationView
|
||||
}
|
||||
|
||||
func mapViewDidFailLoadingMap(_ mapView: MGLMapView, withError error: Error) {
|
||||
|
||||
MXLog.error("[RoomTimelineLocationView] Failed to load map with error: \(error)")
|
||||
|
||||
self.isMapViewLoadingFailed = true
|
||||
}
|
||||
|
||||
func mapViewDidFinishLoadingMap(_ mapView: MGLMapView) {
|
||||
self.isMapViewLoadingFailed = false
|
||||
}
|
||||
|
||||
// MARK: - Action
|
||||
|
||||
@IBAction private func didTapTightButton(_ sender: Any) {
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="RoomTimelineLocationView" customModule="Riot" customModuleProvider="target">
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="RoomTimelineLocationView" customModule="Element" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="395" height="250"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
|
@ -24,6 +24,62 @@
|
|||
<constraint firstAttribute="width" constant="45" id="q3h-Mg-lG4"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XkV-iZ-sfD">
|
||||
<rect key="frame" x="0.0" y="0.0" width="395" height="250"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4gW-5c-wLy">
|
||||
<rect key="frame" x="0.0" y="0.0" width="395" height="182"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NlS-uE-OrS">
|
||||
<rect key="frame" x="50.5" y="52" width="294.5" height="78.5"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="location_map_error" translatesAutoresizingMaskIntoConstraints="NO" id="ror-cm-dP7">
|
||||
<rect key="frame" x="131" y="5" width="32" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="32" id="IpE-8Q-U1X"/>
|
||||
<constraint firstAttribute="width" constant="32" id="diE-aQ-iGF"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Eml-nq-quj">
|
||||
<rect key="frame" x="15" y="47" width="264.5" height="26.5"/>
|
||||
<string key="text">Unable to load map
|
||||
This homeserver is not configured to display maps</string>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="Eml-nq-quj" secondAttribute="trailing" constant="15" id="J2n-U6-RWG"/>
|
||||
<constraint firstItem="ror-cm-dP7" firstAttribute="centerX" secondItem="NlS-uE-OrS" secondAttribute="centerX" id="MtV-hn-HJI"/>
|
||||
<constraint firstItem="Eml-nq-quj" firstAttribute="top" secondItem="ror-cm-dP7" secondAttribute="bottom" constant="10" id="RSS-ta-Ycc"/>
|
||||
<constraint firstItem="Eml-nq-quj" firstAttribute="leading" secondItem="NlS-uE-OrS" secondAttribute="leading" constant="15" id="SJs-dd-Xp2"/>
|
||||
<constraint firstAttribute="width" priority="250" id="bQp-M0-ad4"/>
|
||||
<constraint firstAttribute="height" priority="250" id="pgg-Tl-wNT"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Eml-nq-quj" secondAttribute="bottom" constant="5" id="qZ2-9M-Jha"/>
|
||||
<constraint firstItem="ror-cm-dP7" firstAttribute="top" secondItem="NlS-uE-OrS" secondAttribute="top" constant="5" id="uB2-Ry-jUz"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="NlS-uE-OrS" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="4gW-5c-wLy" secondAttribute="leading" id="D4Y-Jn-aKa"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="NlS-uE-OrS" secondAttribute="bottom" id="GZv-Aw-Qdq"/>
|
||||
<constraint firstItem="NlS-uE-OrS" firstAttribute="top" relation="greaterThanOrEqual" secondItem="4gW-5c-wLy" secondAttribute="top" id="QnJ-vE-nWS"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="NlS-uE-OrS" secondAttribute="trailing" id="h7C-La-6Dc"/>
|
||||
<constraint firstItem="NlS-uE-OrS" firstAttribute="centerY" secondItem="4gW-5c-wLy" secondAttribute="centerY" id="k3F-mp-2pw"/>
|
||||
<constraint firstItem="NlS-uE-OrS" firstAttribute="centerX" secondItem="4gW-5c-wLy" secondAttribute="centerX" id="rfi-Zz-UfZ"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="4gW-5c-wLy" firstAttribute="leading" secondItem="XkV-iZ-sfD" secondAttribute="leading" id="6Yv-CA-oUv"/>
|
||||
<constraint firstAttribute="trailing" secondItem="4gW-5c-wLy" secondAttribute="trailing" id="jge-Zc-VzB"/>
|
||||
<constraint firstItem="4gW-5c-wLy" firstAttribute="top" secondItem="XkV-iZ-sfD" secondAttribute="top" id="ojd-BO-iRA"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="0D1-Km-vTu">
|
||||
<rect key="frame" x="0.0" y="182" width="395" height="68"/>
|
||||
<subviews>
|
||||
|
@ -159,9 +215,14 @@
|
|||
<constraints>
|
||||
<constraint firstItem="1j3-sd-BvY" firstAttribute="centerY" secondItem="4WL-gT-HBV" secondAttribute="centerY" id="A5v-W4-VaN"/>
|
||||
<constraint firstAttribute="trailing" secondItem="vuV-BV-bbx" secondAttribute="trailing" id="Gck-1z-j8f"/>
|
||||
<constraint firstAttribute="bottom" secondItem="XkV-iZ-sfD" secondAttribute="bottom" id="LU8-RW-Azf"/>
|
||||
<constraint firstItem="vuV-BV-bbx" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="NhI-xD-L7V"/>
|
||||
<constraint firstAttribute="trailing" secondItem="0D1-Km-vTu" secondAttribute="trailing" id="QHD-xv-nfX"/>
|
||||
<constraint firstAttribute="trailing" secondItem="XkV-iZ-sfD" secondAttribute="trailing" id="ZdZ-d1-u47"/>
|
||||
<constraint firstItem="XkV-iZ-sfD" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="a2R-cf-5Tn"/>
|
||||
<constraint firstItem="XkV-iZ-sfD" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="c6b-kS-Dlf"/>
|
||||
<constraint firstAttribute="bottom" secondItem="vuV-BV-bbx" secondAttribute="bottom" id="eKg-25-HDW"/>
|
||||
<constraint firstItem="0D1-Km-vTu" firstAttribute="top" secondItem="4gW-5c-wLy" secondAttribute="bottom" id="eQz-kf-RIl"/>
|
||||
<constraint firstItem="4WL-gT-HBV" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="eRF-LN-Evm"/>
|
||||
<constraint firstAttribute="bottom" secondItem="0D1-Km-vTu" secondAttribute="bottom" id="ea5-xx-V3s"/>
|
||||
<constraint firstItem="1j3-sd-BvY" firstAttribute="centerX" secondItem="4WL-gT-HBV" secondAttribute="centerX" id="fxh-rF-fpN"/>
|
||||
|
@ -183,6 +244,9 @@
|
|||
<outlet property="liveLocationIconBackgroundView" destination="72o-VM-Ls7" id="2XU-x0-vhz"/>
|
||||
<outlet property="liveLocationStatusLabel" destination="X9R-EV-RDT" id="HJr-cE-icv"/>
|
||||
<outlet property="liveLocationTimerLabel" destination="U75-c5-got" id="RkO-6a-ABU"/>
|
||||
<outlet property="mapLoadingErrorContainerView" destination="XkV-iZ-sfD" id="kAm-JY-kRA"/>
|
||||
<outlet property="mapLoadingErrorImageView" destination="ror-cm-dP7" id="oXd-fx-43J"/>
|
||||
<outlet property="mapLoadingErrorMessageLabel" destination="Eml-nq-quj" id="Yix-87-5R6"/>
|
||||
<outlet property="placeholderBackground" destination="vuV-BV-bbx" id="9PW-RW-tFh"/>
|
||||
<outlet property="placeholderIconView" destination="4WL-gT-HBV" id="pqw-gN-2Q7"/>
|
||||
<outlet property="rightButton" destination="k5H-UE-ygH" id="nz0-Eb-SRp"/>
|
||||
|
@ -194,6 +258,7 @@
|
|||
<image name="location_background_light_image" width="847.5" height="556"/>
|
||||
<image name="location_live_cell_ended_light_icon" width="46" height="65"/>
|
||||
<image name="location_live_cell_icon" width="32" height="32"/>
|
||||
<image name="location_map_error" width="33" height="32"/>
|
||||
<image name="location_marker_icon" width="24" height="24"/>
|
||||
<systemColor name="systemBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
|
|
|
@ -57,6 +57,8 @@ struct LiveLocationSharingViewerViewState: BindableState {
|
|||
var isBottomSheetVisible: Bool {
|
||||
return isAllLocationSharingEnded == false
|
||||
}
|
||||
|
||||
var showMapLoadingError: Bool = false
|
||||
|
||||
let errorSubject = PassthroughSubject<LocationSharingViewError, Never>()
|
||||
|
||||
|
|
|
@ -105,6 +105,10 @@ class LiveLocationSharingViewerViewModel: LiveLocationSharingViewerViewModelType
|
|||
return
|
||||
}
|
||||
|
||||
if case .failedLoadingMap = error {
|
||||
state.showMapLoadingError = true
|
||||
}
|
||||
|
||||
let alertInfo = mapViewErrorAlertInfoBuilder.build(with: error) { [weak self] in
|
||||
|
||||
switch error {
|
||||
|
|
|
@ -37,40 +37,53 @@ struct LiveLocationSharingViewer: View {
|
|||
|
||||
var body: some View {
|
||||
ZStack(alignment: .bottom) {
|
||||
LocationSharingMapView(tileServerMapURL: viewModel.viewState.mapStyleURL,
|
||||
annotations: viewModel.viewState.annotations,
|
||||
highlightedAnnotation: viewModel.viewState.highlightedAnnotation,
|
||||
userAvatarData: nil,
|
||||
showsUserLocation: false,
|
||||
userAnnotationCanShowCallout: true,
|
||||
userLocation: Binding.constant(nil),
|
||||
mapCenterCoordinate: Binding.constant(nil),
|
||||
onCalloutTap: { annotation in
|
||||
if let userLocationAnnotation = annotation as? UserLocationAnnotation {
|
||||
viewModel.send(viewAction: .share(userLocationAnnotation))
|
||||
}
|
||||
},
|
||||
errorSubject: viewModel.viewState.errorSubject)
|
||||
|
||||
if viewModel.viewState.isBottomSheetVisible {
|
||||
VStack(alignment: .center) {
|
||||
Spacer()
|
||||
MapCreditsView(action: {
|
||||
viewModel.send(viewAction: .mapCreditsDidTap)
|
||||
})
|
||||
.offset(y: -(bottomSheetCollapsedHeight)) // Put the copyright action above the collapsed bottom sheet
|
||||
.padding(.bottom, 10)
|
||||
if !viewModel.viewState.showMapLoadingError {
|
||||
LocationSharingMapView(tileServerMapURL: viewModel.viewState.mapStyleURL,
|
||||
annotations: viewModel.viewState.annotations,
|
||||
highlightedAnnotation: viewModel.viewState.highlightedAnnotation,
|
||||
userAvatarData: nil,
|
||||
showsUserLocation: false,
|
||||
userAnnotationCanShowCallout: true,
|
||||
userLocation: Binding.constant(nil),
|
||||
mapCenterCoordinate: Binding.constant(nil),
|
||||
onCalloutTap: { annotation in
|
||||
if let userLocationAnnotation = annotation as? UserLocationAnnotation {
|
||||
viewModel.send(viewAction: .share(userLocationAnnotation))
|
||||
}
|
||||
},
|
||||
errorSubject: viewModel.viewState.errorSubject)
|
||||
|
||||
// Show map credits above collapsed bottom sheet height if bottom sheet is visible
|
||||
if viewModel.viewState.isBottomSheetVisible {
|
||||
VStack(alignment: .center) {
|
||||
Spacer()
|
||||
MapCreditsView(action: {
|
||||
viewModel.send(viewAction: .mapCreditsDidTap)
|
||||
})
|
||||
.offset(y: -(bottomSheetCollapsedHeight)) // Put the copyright action above the collapsed bottom sheet
|
||||
.padding(.bottom, 10)
|
||||
}
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
.ignoresSafeArea()
|
||||
|
||||
} else {
|
||||
MapLoadingErrorView()
|
||||
.padding(.bottom, viewModel.viewState.isBottomSheetVisible ? bottomSheetCollapsedHeight : 0)
|
||||
}
|
||||
|
||||
if viewModel.viewState.isAllLocationSharingEnded {
|
||||
VStack(alignment: .center) {
|
||||
Spacer()
|
||||
MapCreditsView(action: {
|
||||
viewModel.send(viewAction: .mapCreditsDidTap)
|
||||
})
|
||||
.padding(.bottom, 5)
|
||||
|
||||
// Show map credits only if map is visible
|
||||
if !viewModel.viewState.showMapLoadingError {
|
||||
MapCreditsView(action: {
|
||||
viewModel.send(viewAction: .mapCreditsDidTap)
|
||||
})
|
||||
.padding(.bottom, 5)
|
||||
}
|
||||
|
||||
HStack(spacing: 10) {
|
||||
Image(uiImage: Asset.Images.locationLiveCellIcon.image)
|
||||
.renderingMode(.template)
|
||||
|
@ -96,6 +109,7 @@ struct LiveLocationSharingViewer: View {
|
|||
}
|
||||
}
|
||||
.accentColor(theme.colors.accent)
|
||||
.background(theme.colors.system.ignoresSafeArea())
|
||||
.bottomSheet(sheet, if: viewModel.viewState.isBottomSheetVisible)
|
||||
.actionSheet(isPresented: $viewModel.showMapCreditsSheet) {
|
||||
return MapCreditsActionSheet(openURL: { url in
|
||||
|
|
|
@ -90,6 +90,8 @@ struct LocationSharingViewState: BindableState {
|
|||
var shareButtonEnabled: Bool {
|
||||
!showLoadingIndicator
|
||||
}
|
||||
|
||||
var showMapLoadingError: Bool = false
|
||||
|
||||
let errorSubject = PassthroughSubject<LocationSharingViewError, Never>()
|
||||
|
||||
|
|
|
@ -137,6 +137,9 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie
|
|||
state.bindings.alertInfo = AlertInfo(id: .mapLoadingError,
|
||||
title: VectorL10n.locationSharingLoadingMapErrorTitle(AppInfo.current.displayName),
|
||||
primaryButton: (VectorL10n.ok, primaryButtonCompletion))
|
||||
|
||||
state.showMapLoadingError = true
|
||||
|
||||
case .failedLocatingUser:
|
||||
state.bindings.alertInfo = AlertInfo(id: .userLocatingError,
|
||||
title: VectorL10n.locationSharingLocatingUserErrorTitle(AppInfo.current.displayName),
|
||||
|
|
|
@ -34,17 +34,28 @@ struct LocationSharingView: View {
|
|||
var body: some View {
|
||||
NavigationView {
|
||||
ZStack(alignment: .bottom) {
|
||||
mapView
|
||||
if !context.viewState.showMapLoadingError {
|
||||
mapView
|
||||
}
|
||||
|
||||
VStack(spacing: 0) {
|
||||
MapCreditsView(action: {
|
||||
context.send(viewAction: .mapCreditsDidTap)
|
||||
})
|
||||
.padding(.bottom, 10.0)
|
||||
.actionSheet(isPresented: $context.showMapCreditsSheet) {
|
||||
return MapCreditsActionSheet(openURL: { url in
|
||||
openURL(url)
|
||||
}).sheet
|
||||
|
||||
if context.viewState.showMapLoadingError {
|
||||
MapLoadingErrorView()
|
||||
} else {
|
||||
// Show map credits only if map is visible
|
||||
|
||||
MapCreditsView(action: {
|
||||
context.send(viewAction: .mapCreditsDidTap)
|
||||
})
|
||||
.padding(.bottom, 10.0)
|
||||
.actionSheet(isPresented: $context.showMapCreditsSheet) {
|
||||
return MapCreditsActionSheet(openURL: { url in
|
||||
openURL(url)
|
||||
}).sheet
|
||||
}
|
||||
}
|
||||
|
||||
buttonsView
|
||||
.background(theme.colors.background)
|
||||
.clipShape(RoundedCornerShape(radius: 8, corners: [.topLeft, .topRight]))
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// Copyright 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.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct MapLoadingErrorView: View {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@Environment(\.theme) private var theme: ThemeSwiftUI
|
||||
|
||||
// MARK: Public
|
||||
|
||||
var action: (() -> Void)?
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
VStack {
|
||||
Image(uiImage: Asset.Images.locationMapError.image)
|
||||
.frame(width: 40, height: 40)
|
||||
Text(VectorL10n.locationSharingMapLoadingError)
|
||||
.multilineTextAlignment(.center)
|
||||
.font(theme.fonts.caption1)
|
||||
.foregroundColor(theme.colors.primaryContent)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(theme.colors.system.ignoresSafeArea())
|
||||
}
|
||||
}
|
||||
|
||||
struct MapLoadingErrorView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
MapLoadingErrorView()
|
||||
}
|
||||
}
|
1
changelog.d/6493.change
Normal file
1
changelog.d/6493.change
Normal file
|
@ -0,0 +1 @@
|
|||
Location sharing: Render fallback UI when tile server unavailable.
|
Loading…
Reference in a new issue