diff --git a/Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/Contents.json index a7fdd32cc..0a20c899a 100644 --- a/Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/Contents.json @@ -19,8 +19,5 @@ "info" : { "author" : "xcode", "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" } } diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 8a71db11e..83f855569 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -2143,6 +2143,8 @@ Tap the + to start adding people."; "location_sharing_static_share_title" = "Send my current location"; "location_sharing_pin_drop_share_title" = "Send this location"; "location_sharing_live_map_callout_title" = "Share location"; +"location_sharing_live_timer_outgoing" = "%@ left"; +"location_sharing_live_timer_incoming" = "Live until %@"; // MARK: - MatrixKit diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 66236b6e3..13aecc0c7 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2771,6 +2771,14 @@ public class VectorL10n: NSObject { public static var locationSharingLiveShareTitle: String { return VectorL10n.tr("Vector", "location_sharing_live_share_title") } + /// Live until %@ + public static func locationSharingLiveTimerIncoming(_ p1: String) -> String { + return VectorL10n.tr("Vector", "location_sharing_live_timer_incoming", p1) + } + /// %@ left + public static func locationSharingLiveTimerOutgoing(_ p1: String) -> String { + return VectorL10n.tr("Vector", "location_sharing_live_timer_outgoing", p1) + } /// %@ could not load the map. Please try again later. public static func locationSharingLoadingMapErrorTitle(_ p1: String) -> String { return VectorL10n.tr("Vector", "location_sharing_loading_map_error_title", p1) diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 6916cbeec..9d0603f6d 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -187,12 +187,6 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat break; } - case MXEventTypeBeaconInfo: - { - self.tag = RoomBubbleCellDataTagLocation; - self.collapsable = NO; - self.collapsed = NO; - } default: break; } diff --git a/Riot/Modules/Room/Location/RoomTimelineLocationView.swift b/Riot/Modules/Room/Location/RoomTimelineLocationView.swift index 6573453fa..4eb372b2d 100644 --- a/Riot/Modules/Room/Location/RoomTimelineLocationView.swift +++ b/Riot/Modules/Room/Location/RoomTimelineLocationView.swift @@ -17,11 +17,28 @@ import UIKit import Reusable import Mapbox +import SwiftUI struct LiveLocationParameter { + let bannerImage: UIImage + let bannerTitle: String + let timer: String? + let shouldShowStopButton: Bool let isLive: Bool - let endTime: Int - let isUser: Bool +} + +enum LiveLocationState { + case incomingLive(String?) + case outgoingLive(String?) + + func values() -> LiveLocationParameter { + switch self { + case .incomingLive(let timerString): + return LiveLocationParameter(bannerImage: Asset.Images.locationLiveIcon.image, bannerTitle: VectorL10n.liveLocationSharingBannerTitle, timer: timerString, shouldShowStopButton: false, isLive: true) + case .outgoingLive(let timerString): + return LiveLocationParameter(bannerImage: Asset.Images.locationLiveIcon.image, bannerTitle: VectorL10n.liveLocationSharingBannerTitle, timer: timerString, shouldShowStopButton: true, isLive: true) + } + } } class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegate { @@ -48,7 +65,8 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat @IBOutlet private var liveLocationImageView: UIImageView! @IBOutlet private var liveLocationStatusLabel: UILabel! @IBOutlet private var liveLocationTimerLabel: UILabel! - @IBOutlet private var stopSharingContainerView: UIView! + @IBOutlet private var stopSharingButton: UIButton! + private var mapView: MGLMapView! @@ -91,7 +109,7 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat public func displayLocation(_ location: CLLocationCoordinate2D, userAvatarData: AvatarViewData? = nil, mapStyleURL: URL, - liveLocationParameter: LiveLocationParameter? = nil) { + liveLocationState: LiveLocationState? = nil) { mapView.styleURL = mapStyleURL @@ -113,14 +131,21 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat mapView.addAnnotation(pointAnnotation) // Configure live location banner - guard let liveLocationParameter = liveLocationParameter else { + guard let liveLocationParameters = liveLocationState?.values() else { liveLocationContainerView.isHidden = true return } liveLocationContainerView.isHidden = false - stopSharingContainerView.isHidden = !liveLocationParameter.isLive - liveLocationTimerLabel.isHidden = !liveLocationParameter.isLive + liveLocationImageView.image = liveLocationParameters.bannerImage + liveLocationStatusLabel.text = liveLocationParameters.bannerTitle + if let timerString = liveLocationParameters.timer { + liveLocationTimerLabel.isHidden = false + liveLocationTimerLabel.text = timerString + } else { + liveLocationTimerLabel.isHidden = true + } + stopSharingButton.isHidden = !liveLocationParameters.shouldShowStopButton } // MARK: - Themable diff --git a/Riot/Modules/Room/Location/RoomTimelineLocationView.xib b/Riot/Modules/Room/Location/RoomTimelineLocationView.xib index da3e09108..c6cdf2ed3 100644 --- a/Riot/Modules/Room/Location/RoomTimelineLocationView.xib +++ b/Riot/Modules/Room/Location/RoomTimelineLocationView.xib @@ -15,16 +15,16 @@ - - + + - - + - - + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - - + + + + + - + - - - - + + + + + + + + + + + diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationPlainCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationPlainCell.swift index 5628f4ef4..4d47dd775 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationPlainCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationPlainCell.swift @@ -33,11 +33,9 @@ class LocationPlainCell: SizableBaseRoomCell, RoomCellReactionsDisplayable, Room locationView.update(theme: ThemeService.shared().theme) - if event.eventType == __MXEventType.roomMessage { - renderStaticLocation(event) - } else if event.eventType == __MXEventType.beaconInfo { - renderLiveLocation(event) - } + // Comment this line and uncomment next one to test UI of live location tile + renderStaticLocation(event) +// renderLiveLocation(event) } private func renderStaticLocation(_ event: MXEvent) { @@ -65,11 +63,57 @@ class LocationPlainCell: SizableBaseRoomCell, RoomCellReactionsDisplayable, Room } private func renderLiveLocation(_ event: MXEvent) { - guard let locationContent = event.content else { + // TODO: - Render live location cell when live location event is handled + + // This code is only for testing live location cell + // Will be completed when the live location event is handled + + guard let locationContent = event.location else { return } + + locationView.locationDescription = locationContent.locationDescription + + let location = CLLocationCoordinate2D(latitude: locationContent.latitude, longitude: locationContent.longitude) + + let mapStyleURL = bubbleData.mxSession.vc_homeserverConfiguration().tileServer.mapStyleURL + + let avatarViewData = AvatarViewData(matrixItemId: bubbleData.senderId, + displayName: bubbleData.senderDisplayName, + avatarUrl: bubbleData.senderAvatarUrl, + mediaManager: bubbleData.mxSession.mediaManager, + fallbackImage: .matrixItem(bubbleData.senderId, bubbleData.senderDisplayName)) + let futurDateTimeInterval = Date(timeIntervalSinceNow: 3734).timeIntervalSince1970 + locationView.displayLocation(location, userAvatarData: avatarViewData, mapStyleURL: mapStyleURL, liveLocationState: .outgoingLive(generateTimerString(for: futurDateTimeInterval, isIncomingLocation: false))) } + private func generateTimerString(for timestamp: Double, + isIncomingLocation: Bool) -> String? { + let timerString: String? + if isIncomingLocation { + timerString = VectorL10n.locationSharingLiveTimerIncoming(incomingTimerFormatter.string(from: Date(timeIntervalSince1970: timestamp))) + } else if let outgoingTimer = outgoingTimerFormatter.string(from: Date(timeIntervalSince1970: timestamp).timeIntervalSinceNow) { + timerString = VectorL10n.locationSharingLiveTimerOutgoing(outgoingTimer) + } else { + timerString = nil + } + return timerString + } + + private lazy var incomingTimerFormatter: DateFormatter = { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "HH:mm" + return dateFormatter + }() + + private lazy var outgoingTimerFormatter: DateComponentsFormatter = { + let formatter = DateComponentsFormatter() + formatter.zeroFormattingBehavior = .dropAll + formatter.allowedUnits = [.hour, .minute, .second] + formatter.unitsStyle = .brief + return formatter + }() + override func setupViews() { super.setupViews() diff --git a/changelog.d/6029.change b/changelog.d/6029.change new file mode 100644 index 000000000..9a829ea07 --- /dev/null +++ b/changelog.d/6029.change @@ -0,0 +1 @@ +Location sharing: Add cell for live location sharing in timeline