From 8004aecf06555a1df0dbe40cee7edce640f5fa16 Mon Sep 17 00:00:00 2001 From: MaximeE Date: Wed, 27 Apr 2022 16:21:42 +0200 Subject: [PATCH] 6077: Implement SDK for live sharing timeline cell --- Config/BuildSettings.swift | 2 +- .../Room/CellData/RoomBubbleCellData.m | 2 +- .../Location/RoomTimelineLocationView.swift | 42 +++++---- .../Cells/Location/LocationPlainCell.swift | 93 +++++++++++++------ 4 files changed, 88 insertions(+), 51 deletions(-) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index cccba278d..1537ef8ed 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -427,6 +427,6 @@ final class BuildSettings: NSObject { } // Do not enable live location sharing atm - return false + return true } } diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 5a4e7b3ca..d79d02ed7 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -168,8 +168,8 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat self.collapsed = NO; [self updateBeaconInfoSummaryWithEventId:event.eventId]; - } break; + } case MXEventTypeCustom: { if ([event.type isEqualToString:kWidgetMatrixEventTypeString] diff --git a/Riot/Modules/Room/Location/RoomTimelineLocationView.swift b/Riot/Modules/Room/Location/RoomTimelineLocationView.swift index c8f680e57..3d43b1564 100644 --- a/Riot/Modules/Room/Location/RoomTimelineLocationView.swift +++ b/Riot/Modules/Room/Location/RoomTimelineLocationView.swift @@ -25,7 +25,7 @@ protocol RoomTimelineLocationViewDelegate: AnyObject { } struct RoomTimelineLocationViewData { - let location: CLLocationCoordinate2D + let location: CLLocationCoordinate2D? let userAvatarData: AvatarViewData? let mapStyleURL: URL } @@ -162,30 +162,34 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat // MARK: - Private - private func displayLocation(_ location: CLLocationCoordinate2D, + private func displayLocation(_ location: CLLocationCoordinate2D?, userAvatarData: AvatarViewData? = nil, mapStyleURL: URL, bannerViewData: LiveLocationBannerViewData? = nil) { - mapView.styleURL = mapStyleURL - - annotationView = LocationMarkerView.loadFromNib() - - if let userAvatarData = userAvatarData { - let avatarBackgroundColor = Self.usernameColorGenerator.color(from: userAvatarData.matrixItemId) - annotationView?.setAvatarData(userAvatarData, avatarBackgroundColor: avatarBackgroundColor) + if let location = location { + mapView.styleURL = mapStyleURL + + annotationView = LocationMarkerView.loadFromNib() + + if let userAvatarData = userAvatarData { + let avatarBackgroundColor = Self.usernameColorGenerator.color(from: userAvatarData.matrixItemId) + annotationView?.setAvatarData(userAvatarData, avatarBackgroundColor: avatarBackgroundColor) + } + + if let annotations = mapView.annotations { + mapView.removeAnnotations(annotations) + } + + mapView.setCenter(location, zoomLevel: Constants.mapZoomLevel, animated: false) + + let pointAnnotation = MGLPointAnnotation() + pointAnnotation.coordinate = location + mapView.addAnnotation(pointAnnotation) + } else { + mapView.isHidden = true } - if let annotations = mapView.annotations { - mapView.removeAnnotations(annotations) - } - - mapView.setCenter(location, zoomLevel: Constants.mapZoomLevel, animated: false) - - let pointAnnotation = MGLPointAnnotation() - pointAnnotation.coordinate = location - mapView.addAnnotation(pointAnnotation) - // Configure live location banner guard let bannerViewData = bannerViewData else { liveLocationContainerView.isHidden = true 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 77f5f784d..6d9c3042f 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationPlainCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationPlainCell.swift @@ -26,18 +26,26 @@ class LocationPlainCell: SizableBaseRoomCell, RoomCellReactionsDisplayable, Room super.render(cellData) guard #available(iOS 14.0, *), - let bubbleData = cellData as? RoomBubbleCellData, - let event = bubbleData.events.last + let bubbleData = cellData as? RoomBubbleCellData else { return } - self.event = event locationView.update(theme: ThemeService.shared().theme) - // Comment this line and uncomment next one to test UI of live location tile - renderStaticLocation(event) -// renderLiveLocation(event) + if bubbleData.cellDataTag == .location, + let event = bubbleData.events.last { + self.event = event + renderStaticLocation(event) + } else if bubbleData.cellDataTag == .liveLocation, + let beaconInfoSummary = bubbleData.beaconInfoSummary { + if bubbleData.mxSession.myUserId == beaconInfoSummary.userId { + renderOutgoingLiveLocation(beaconInfoSummary) + } else if bubbleData.senderId == beaconInfoSummary.userId { + renderIncomingLiveLocation(beaconInfoSummary) + } + + } } private func renderStaticLocation(_ event: MXEvent) { @@ -55,10 +63,10 @@ class LocationPlainCell: SizableBaseRoomCell, RoomCellReactionsDisplayable, Room if locationContent.assetType == .user { avatarViewData = AvatarViewData(matrixItemId: bubbleData.senderId, - displayName: bubbleData.senderDisplayName, - avatarUrl: bubbleData.senderAvatarUrl, - mediaManager: bubbleData.mxSession.mediaManager, - fallbackImage: .matrixItem(bubbleData.senderId, bubbleData.senderDisplayName)) + displayName: bubbleData.senderDisplayName, + avatarUrl: bubbleData.senderAvatarUrl, + mediaManager: bubbleData.mxSession.mediaManager, + fallbackImage: .matrixItem(bubbleData.senderId, bubbleData.senderDisplayName)) } else { avatarViewData = nil } @@ -66,31 +74,56 @@ class LocationPlainCell: SizableBaseRoomCell, RoomCellReactionsDisplayable, Room locationView.displayStaticLocation(with: RoomTimelineLocationViewData(location: location, userAvatarData: avatarViewData, mapStyleURL: mapStyleURL)) } - private func renderLiveLocation(_ event: MXEvent) { - // 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 - + private func renderIncomingLiveLocation(_ beaconInfoSummary: MXBeaconInfoSummaryProtocol) { + let liveLocationStatus: IncomingLiveLocationSharingStatus + var location: CLLocationCoordinate2D? 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 * 1000 + let mapStyleURL = bubbleData.mxSession.vc_homeserverConfiguration().tileServer.mapStyleURL + + if beaconInfoSummary.lastBeacon == nil { + liveLocationStatus = .starting + } else if beaconInfoSummary.hasStopped || beaconInfoSummary.hasExpired { + liveLocationStatus = .stopped + } else { + liveLocationStatus = .started(TimeInterval(beaconInfoSummary.expiryTimestamp)) + } + + if let mxLocation = beaconInfoSummary.lastBeacon?.location { + location = CLLocationCoordinate2D(latitude: mxLocation.latitude, longitude: mxLocation.longitude) + } locationView.displayLiveLocation(with: RoomTimelineLocationViewData(location: location, userAvatarData: avatarViewData, mapStyleURL: mapStyleURL), - liveLocationViewState: .outgoing(.started(futurDateTimeInterval))) + liveLocationViewState: .incoming(liveLocationStatus)) + } + + private func renderOutgoingLiveLocation(_ beaconInfoSummary: MXBeaconInfoSummaryProtocol) { + let liveLocationStatus: OutgoingLiveLocationSharingStatus + var location: CLLocationCoordinate2D? + let avatarViewData = AvatarViewData(matrixItemId: bubbleData.senderId, + displayName: bubbleData.senderDisplayName, + avatarUrl: bubbleData.senderAvatarUrl, + mediaManager: bubbleData.mxSession.mediaManager, + fallbackImage: .matrixItem(bubbleData.senderId, bubbleData.senderDisplayName)) + let mapStyleURL = bubbleData.mxSession.vc_homeserverConfiguration().tileServer.mapStyleURL + + if beaconInfoSummary.lastBeacon == nil { + liveLocationStatus = .starting + } else if beaconInfoSummary.hasStopped || beaconInfoSummary.hasExpired { + liveLocationStatus = .stopped + } else { + liveLocationStatus = .started(TimeInterval(beaconInfoSummary.expiryTimestamp)) + } + + if let mxLocation = beaconInfoSummary.lastBeacon?.location { + location = CLLocationCoordinate2D(latitude: mxLocation.latitude, longitude: mxLocation.longitude) + } + + locationView.displayLiveLocation(with: RoomTimelineLocationViewData(location: location, userAvatarData: avatarViewData, mapStyleURL: mapStyleURL), + liveLocationViewState: .outgoing(liveLocationStatus)) } override func setupViews() { @@ -102,8 +135,8 @@ class LocationPlainCell: SizableBaseRoomCell, RoomCellReactionsDisplayable, Room guard #available(iOS 14.0, *), let contentView = roomCellContentView?.innerContentView else { - return - } + return + } locationView = RoomTimelineLocationView.loadFromNib()