Merge branch 'ismail/5068_start_thread' into ismail/5068_design_tweaks

This commit is contained in:
ismailgulek
2022-01-17 11:37:41 +03:00
300 changed files with 6263 additions and 923 deletions
@@ -32,7 +32,8 @@ typedef NS_ENUM(NSInteger, RoomBubbleCellDataTag)
RoomBubbleCellDataTagCall,
RoomBubbleCellDataTagGroupCall,
RoomBubbleCellDataTagRoomCreationIntro,
RoomBubbleCellDataTagPoll
RoomBubbleCellDataTagPoll,
RoomBubbleCellDataTagLocation
};
/**
@@ -174,8 +174,17 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
self.displayTimestampForSelectedComponentOnLeftWhenPossible = NO;
}
}
}
break;
}
case MXEventTypeRoomMessage:
{
if (event.location) {
self.tag = RoomBubbleCellDataTagLocation;
self.collapsable = NO;
self.collapsed = NO;
}
}
default:
break;
}
@@ -273,6 +282,11 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
return NO;
}
if (self.tag == RoomBubbleCellDataTagLocation)
{
return NO;
}
return [super hasNoDisplay];
}
@@ -885,6 +899,9 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
case RoomBubbleCellDataTagPoll:
shouldAddEvent = NO;
break;
case RoomBubbleCellDataTagLocation:
shouldAddEvent = NO;
break;
default:
break;
}
@@ -897,7 +914,12 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
{
case MXEventTypeRoomMessage:
{
NSString *messageType = event.content[@"msgtype"];
if (event.location) {
shouldAddEvent = NO;
break;
}
NSString *messageType = event.content[kMXMessageTypeKey];
if ([messageType isEqualToString:kMXMessageTypeKeyVerificationRequest])
{
@@ -1031,7 +1053,7 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
break;
case MXEventTypeRoomMessage:
{
NSString *msgType = event.content[@"msgtype"];
NSString *msgType = event.content[kMXMessageTypeKey];
if ([msgType isEqualToString:kMXMessageTypeKeyVerificationRequest])
{
@@ -1084,7 +1106,7 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
{
NSString *mediaName = [self accessibilityLabelForAttachmentType:self.attachment.type];
MXJSONModelSetString(accessibilityLabel, self.events.firstObject.content[@"body"]);
MXJSONModelSetString(accessibilityLabel, self.events.firstObject.content[kMXMessageBodyKey]);
if (accessibilityLabel)
{
accessibilityLabel = [NSString stringWithFormat:@"%@ %@", mediaName, accessibilityLabel];
@@ -1115,9 +1137,6 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
case MXKAttachmentTypeVideo:
accessibilityLabel = [VectorL10n mediaTypeAccessibilityVideo];
break;
case MXKAttachmentTypeLocation:
accessibilityLabel = [VectorL10n mediaTypeAccessibilityLocation];
break;
case MXKAttachmentTypeFile:
accessibilityLabel = [VectorL10n mediaTypeAccessibilityFile];
break;
@@ -922,7 +922,7 @@ const CGFloat kTypingCellHeight = 24;
break;
case MXEventTypeRoomMessage:
{
NSString *msgType = event.content[@"msgtype"];
NSString *msgType = event.content[kMXMessageTypeKey];
if ([msgType isEqualToString:kMXMessageTypeKeyVerificationRequest])
{
@@ -0,0 +1,33 @@
//
// Copyright 2021 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 UIKit
import Reusable
import Mapbox
class LocationUserMarkerView: MGLAnnotationView, NibLoadable {
@IBOutlet private var avatarView: UserAvatarView!
override func awakeFromNib() {
super.awakeFromNib()
translatesAutoresizingMaskIntoConstraints = false
}
func setAvatarData(_ avatarData: AvatarViewDataProtocol) {
avatarView.fill(with: avatarData)
}
}
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" 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="18093"/>
<capability name="Safe area layout guides" minToolsVersion="9.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="LocationUserMarkerView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="50" height="54"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="location_user_marker" translatesAutoresizingMaskIntoConstraints="NO" id="ldO-kc-R5W">
<rect key="frame" x="0.0" y="0.0" width="50" height="54"/>
</imageView>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qut-wn-BX3" customClass="UserAvatarView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="2" y="2" width="46" height="46"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="ldO-kc-R5W" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="VF5-CP-8eH"/>
<constraint firstItem="ldO-kc-R5W" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="Voc-LH-fTw"/>
<constraint firstAttribute="trailing" secondItem="ldO-kc-R5W" secondAttribute="trailing" id="Vt0-UN-s20"/>
<constraint firstAttribute="bottom" secondItem="ldO-kc-R5W" secondAttribute="bottom" id="Ybf-8x-UaG"/>
</constraints>
<nil key="simulatedTopBarMetrics"/>
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="avatarView" destination="qut-wn-BX3" id="wHA-bz-A2y"/>
</connections>
<point key="canvasLocation" x="-84.057971014492765" y="-80.357142857142847"/>
</view>
</objects>
<resources>
<image name="location_user_marker" width="51" height="54.5"/>
</resources>
</document>
@@ -0,0 +1,114 @@
//
// Copyright 2021 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 UIKit
import Reusable
import Mapbox
import Keys
class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegate {
// MARK: - Constants
private struct Constants {
static let mapHeight: CGFloat = 300.0
static let mapTilerKey = RiotKeys().mapTilerAPIKey
static let mapZoomLevel = 15.0
static let cellBorderRadius: CGFloat = 1.0
static let cellCornerRadius: CGFloat = 8.0
}
// MARK: - Properties
// MARK: Private
@IBOutlet private var descriptionContainerView: UIView!
@IBOutlet private var descriptionLabel: UILabel!
private var mapView: MGLMapView!
private var annotationView: LocationUserMarkerView?
// MARK: Public
var locationDescription: String? {
get {
descriptionLabel.text
}
set {
descriptionLabel.text = newValue
descriptionContainerView.isHidden = (newValue?.count ?? 0 == 0)
}
}
override func awakeFromNib() {
super.awakeFromNib()
mapView = MGLMapView(frame: .zero, styleURL: BuildSettings.tileServerMapURL)
mapView.delegate = self
mapView.logoView.isHidden = true
mapView.attributionButton.isHidden = true
mapView.isUserInteractionEnabled = false
mapView.translatesAutoresizingMaskIntoConstraints = false
mapView.addConstraint(mapView.heightAnchor.constraint(equalToConstant: Constants.mapHeight))
vc_addSubViewMatchingParent(mapView)
sendSubviewToBack(mapView)
clipsToBounds = true
layer.borderWidth = Constants.cellBorderRadius
layer.cornerRadius = Constants.cellCornerRadius
}
// MARK: - Public
public func displayLocation(_ location: CLLocationCoordinate2D,
userIdentifier: String,
userDisplayName: String,
userAvatarURLString: String?,
mediaManager: MXMediaManager) {
annotationView = LocationUserMarkerView.loadFromNib()
annotationView?.setAvatarData(AvatarViewData(matrixItemId: userIdentifier,
displayName: userDisplayName,
avatarUrl: userAvatarURLString,
mediaManager: mediaManager,
fallbackImage: .matrixItem(userIdentifier, userDisplayName)))
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)
}
// MARK: - Themable
func update(theme: Theme) {
descriptionLabel.textColor = theme.colors.primaryContent
descriptionLabel.font = theme.fonts.footnote
layer.borderColor = theme.colors.quinaryContent.cgColor
}
// MARK: - MGLMapViewDelegate
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
return annotationView
}
}
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" 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="18093"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<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">
<rect key="frame" x="0.0" y="0.0" width="395" height="250"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oVd-gS-Rmb">
<rect key="frame" x="0.0" y="210" width="395" height="40"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="XHz-4S-fh4">
<rect key="frame" x="12" y="8" width="371" height="24"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="location_marker_icon" translatesAutoresizingMaskIntoConstraints="NO" id="GP2-dA-giJ">
<rect key="frame" x="0.0" y="0.0" width="24" height="24"/>
<constraints>
<constraint firstAttribute="width" constant="24" id="7nK-Kb-7Iq"/>
<constraint firstAttribute="height" constant="24" id="nBW-gN-0uW"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="c68-l7-McA">
<rect key="frame" x="32" y="2" width="339" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="XHz-4S-fh4" secondAttribute="trailing" constant="12" id="FI1-B7-bPV"/>
<constraint firstItem="XHz-4S-fh4" firstAttribute="top" secondItem="oVd-gS-Rmb" secondAttribute="top" constant="8" id="UJq-Yz-ikR"/>
<constraint firstAttribute="bottom" secondItem="XHz-4S-fh4" secondAttribute="bottom" constant="8" id="cvr-Gb-uLe"/>
<constraint firstItem="XHz-4S-fh4" firstAttribute="leading" secondItem="oVd-gS-Rmb" secondAttribute="leading" constant="12" id="wSE-NS-2h4"/>
</constraints>
</view>
</subviews>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="oVd-gS-Rmb" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="6Vw-QI-iN2"/>
<constraint firstItem="oVd-gS-Rmb" firstAttribute="bottom" secondItem="vUN-kp-3ea" secondAttribute="bottom" id="FVf-yb-Gxc"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="oVd-gS-Rmb" secondAttribute="trailing" id="O3u-fm-TxC"/>
</constraints>
<nil key="simulatedTopBarMetrics"/>
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="descriptionContainerView" destination="oVd-gS-Rmb" id="Npu-jp-oYo"/>
<outlet property="descriptionLabel" destination="c68-l7-McA" id="HiH-8Q-yTp"/>
</connections>
<point key="canvasLocation" x="165.94202898550725" y="-100.78125"/>
</view>
</objects>
<resources>
<image name="location_marker_icon" width="24" height="24"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
+73 -6
View File
@@ -30,8 +30,6 @@ final class RoomCoordinator: NSObject, RoomCoordinatorProtocol {
private let activityIndicatorPresenter: ActivityIndicatorPresenterType
private var selectedEventId: String?
private var pollEditFormCoordinator: PollEditFormCoordinator?
private var roomDataSourceManager: MXKRoomDataSourceManager {
return MXKRoomDataSourceManager.sharedManager(forMatrixSession: self.parameters.session)
}
@@ -241,7 +239,56 @@ final class RoomCoordinator: NSObject, RoomCoordinatorProtocol {
completion?()
}
private func startLocationCoordinatorWithEvent(_ event: MXEvent? = nil, bubbleData: MXKRoomBubbleCellDataStoring? = nil) {
guard #available(iOS 14.0, *) else {
return
}
guard let navigationRouter = self.navigationRouter,
let mediaManager = mxSession?.mediaManager,
let user = mxSession?.myUser else {
MXLog.error("[RoomCoordinator] Invalid location sharing coordinator parameters. Returning.")
return
}
var avatarData: AvatarInputProtocol
if event != nil, let bubbleData = bubbleData {
avatarData = AvatarInput(mxContentUri: bubbleData.senderAvatarUrl,
matrixItemId: bubbleData.senderId,
displayName: bubbleData.senderDisplayName)
} else {
avatarData = AvatarInput(mxContentUri: user.avatarUrl,
matrixItemId: user.userId,
displayName: user.displayname)
}
var location: CLLocationCoordinate2D?
if let locationContent = event?.location {
location = CLLocationCoordinate2D(latitude: locationContent.latitude, longitude: locationContent.longitude)
}
let parameters = LocationSharingCoordinatorParameters(roomDataSource: roomViewController.roomDataSource,
mediaManager: mediaManager,
avatarData: avatarData,
location: location)
let coordinator = LocationSharingCoordinator(parameters: parameters)
coordinator.completion = { [weak self, weak coordinator] in
guard let self = self, let coordinator = coordinator else {
return
}
self.navigationRouter?.dismissModule(animated: true, completion: nil)
self.remove(childCoordinator: coordinator)
}
add(childCoordinator: coordinator)
navigationRouter.present(coordinator, animated: true)
coordinator.start()
}
}
// MARK: - RoomIdentifiable
@@ -309,10 +356,30 @@ extension RoomCoordinator: RoomViewControllerDelegate {
return
}
let parameters = PollEditFormCoordinatorParameters(navigationRouter: self.navigationRouter, room: roomViewController.roomDataSource.room)
pollEditFormCoordinator = PollEditFormCoordinator(parameters: parameters)
let parameters = PollEditFormCoordinatorParameters(room: roomViewController.roomDataSource.room)
let coordinator = PollEditFormCoordinator(parameters: parameters)
pollEditFormCoordinator?.start()
coordinator.completion = { [weak self, weak coordinator] in
guard let self = self, let coordinator = coordinator else {
return
}
self.navigationRouter?.dismissModule(animated: true, completion: nil)
self.remove(childCoordinator: coordinator)
}
add(childCoordinator: coordinator)
navigationRouter?.present(coordinator, animated: true)
coordinator.start()
}
func roomViewControllerDidRequestLocationSharingFormPresentation(_ roomViewController: RoomViewController) {
startLocationCoordinatorWithEvent()
}
func roomViewController(_ roomViewController: RoomViewController, didRequestLocationPresentationFor event: MXEvent, bubbleData: MXKRoomBubbleCellDataStoring) {
startLocationCoordinatorWithEvent(event, bubbleData: bubbleData)
}
func roomViewController(_ roomViewController: RoomViewController, canEndPollWithEventIdentifier eventIdentifier: String) -> Bool {
+18
View File
@@ -201,6 +201,24 @@ handleUniversalLinkWithParameters:(UniversalLinkParameters*)parameters;
*/
- (void)roomViewControllerDidRequestPollCreationFormPresentation:(RoomViewController *)roomViewController;
/**
Ask the coordinator to invoke the location sharing form coordinator.
@param roomViewController the `RoomViewController` instance.
*/
- (void)roomViewControllerDidRequestLocationSharingFormPresentation:(RoomViewController *)roomViewController;
/**
Ask the coordinator to invoke the location sharing form coordinator.
@param roomViewController the `RoomViewController` instance.
@param event the event containing location information
@param bubbleData the bubble data containing sender details
*/
- (void)roomViewController:(RoomViewController *)roomViewController
didRequestLocationPresentationForEvent:(MXEvent *)event
bubbleData:(id<MXKRoomBubbleCellDataStoring>)bubbleData;
- (BOOL)roomViewController:(RoomViewController *)roomViewController
canEndPollWithEventIdentifier:(NSString *)eventIdentifier;
+49 -3
View File
@@ -442,6 +442,10 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self.bubblesTableView registerClass:PollBubbleCell.class forCellReuseIdentifier:PollBubbleCell.defaultReuseIdentifier];
[self.bubblesTableView registerClass:PollWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:PollWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
[self.bubblesTableView registerClass:PollWithPaginationTitleBubbleCell.class forCellReuseIdentifier:PollWithPaginationTitleBubbleCell.defaultReuseIdentifier];
[self.bubblesTableView registerClass:LocationBubbleCell.class forCellReuseIdentifier:LocationBubbleCell.defaultReuseIdentifier];
[self.bubblesTableView registerClass:LocationWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:LocationWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
[self.bubblesTableView registerClass:LocationWithPaginationTitleBubbleCell.class forCellReuseIdentifier:LocationWithPaginationTitleBubbleCell.defaultReuseIdentifier];
[self vc_removeBackTitle];
@@ -2099,6 +2103,16 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self.delegate roomViewControllerDidRequestPollCreationFormPresentation:self];
}]];
}
if (RiotSettings.shared.roomScreenAllowLocationAction)
{
[actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_location"] andAction:^{
MXStrongifyAndReturnIfNil(self);
if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) {
((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO;
}
[self.delegate roomViewControllerDidRequestLocationSharingFormPresentation:self];
}]];
}
if (RiotSettings.shared.roomScreenAllowCameraAction)
{
[actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_camera"] andAction:^{
@@ -2798,6 +2812,21 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
cellViewClass = PollBubbleCell.class;
}
}
else if (bubbleData.tag == RoomBubbleCellDataTagLocation)
{
if (bubbleData.isPaginationFirstBubble)
{
cellViewClass = LocationWithPaginationTitleBubbleCell.class;
}
else if (bubbleData.shouldHideSenderInformation)
{
cellViewClass = LocationWithoutSenderInfoBubbleCell.class;
}
else
{
cellViewClass = LocationBubbleCell.class;
}
}
else if (bubbleData.isIncoming)
{
if (bubbleData.isAttachmentWithThumbnail)
@@ -2998,7 +3027,11 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
else
{
[self showContextualMenuForEvent:tappedEvent fromSingleTapGesture:YES cell:cell animated:YES];
if (tappedEvent.location) {
[_delegate roomViewController:self didRequestLocationPresentationForEvent:tappedEvent bubbleData:bubbleData];
} else {
[self showContextualMenuForEvent:tappedEvent fromSingleTapGesture:YES cell:cell animated:YES];
}
}
}
}
@@ -3351,7 +3384,20 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self cancelEventSelection];
}]];
}
if (selectedEvent.sentState == MXEventSentStateSent &&
selectedEvent.eventType != MXEventTypePollStart &&
!selectedEvent.location)
{
[self.eventMenuBuilder addItemWithType:EventMenuItemTypeForwards
action:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionForward]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
[self presentEventForwardingDialogForSelectedEvent:selectedEvent];
}]];
}
if (!isJitsiCallEvent && selectedEvent.eventType != MXEventTypePollStart)
{
[self.eventMenuBuilder addItemWithType:EventMenuItemTypeQuote
@@ -6317,7 +6363,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
switch (event.eventType) {
case MXEventTypeRoomMessage:
{
NSString *messageType = event.content[@"msgtype"];
NSString *messageType = event.content[kMXMessageTypeKey];
if ([messageType isEqualToString:kMXMessageTypeKeyVerificationRequest])
{
@@ -140,14 +140,14 @@
</constraints>
</stackView>
<view clipsSubviews="YES" contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="oeI-eO-mFK">
<rect key="frame" x="56" y="3" width="524" height="91"/>
<rect key="frame" x="56" y="3" width="524" height="78"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="oeI-eO-mFK" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="vcq-cR-uBc" secondAttribute="leading" constant="56" id="0Fr-0L-9tU"/>
<constraint firstAttribute="bottom" secondItem="oeI-eO-mFK" secondAttribute="bottom" constant="3" id="8M5-uW-82s"/>
<constraint firstAttribute="bottom" secondItem="oeI-eO-mFK" secondAttribute="bottom" constant="16" id="8M5-uW-82s"/>
<constraint firstItem="oeI-eO-mFK" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="4d4-XQ-ido" secondAttribute="trailing" constant="6" id="9By-U1-wTY"/>
<constraint firstAttribute="trailing" secondItem="oeI-eO-mFK" secondAttribute="trailing" constant="15" id="Pbe-4d-q6Y"/>
<constraint firstAttribute="bottom" secondItem="4d4-XQ-ido" secondAttribute="bottom" id="Tkw-p1-CYF"/>
@@ -0,0 +1,63 @@
//
// Copyright 2021 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 Foundation
class LocationBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable {
private var locationView: RoomTimelineLocationView!
override func render(_ cellData: MXKCellData!) {
super.render(cellData)
guard #available(iOS 14.0, *),
let bubbleData = cellData as? RoomBubbleCellData,
let event = bubbleData.events.last,
event.eventType == __MXEventType.roomMessage,
let locationContent = event.location
else {
return
}
locationView.update(theme: ThemeService.shared().theme)
locationView.locationDescription = locationContent.locationDescription
let location = CLLocationCoordinate2D(latitude: locationContent.latitude, longitude: locationContent.longitude)
locationView.displayLocation(location,
userIdentifier: bubbleData.senderId,
userDisplayName: bubbleData.senderDisplayName,
userAvatarURLString: bubbleData.senderAvatarUrl,
mediaManager: bubbleData.mxSession.mediaManager)
}
override func setupViews() {
super.setupViews()
bubbleCellContentView?.backgroundColor = .clear
bubbleCellContentView?.showSenderInfo = true
bubbleCellContentView?.showPaginationTitle = false
guard #available(iOS 14.0, *),
let contentView = bubbleCellContentView?.innerContentView else {
return
}
locationView = RoomTimelineLocationView.loadFromNib()
contentView.vc_addSubViewMatchingParent(locationView)
}
}
@@ -0,0 +1,25 @@
//
// Copyright 2021 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 Foundation
class LocationWithPaginationTitleBubbleCell: LocationBubbleCell {
override func setupViews() {
super.setupViews()
bubbleCellContentView?.showPaginationTitle = true
}
}
@@ -0,0 +1,25 @@
//
// Copyright 2021 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 Foundation
class LocationWithoutSenderInfoBubbleCell: LocationBubbleCell {
override func setupViews() {
super.setupViews()
bubbleCellContentView?.showSenderInfo = false
}
}
@@ -0,0 +1,23 @@
//
// Copyright 2021 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 Foundation
/// Represents the room timeline style identifiers available
enum RoomTimelineStyleIdentifier {
case plain
case bubble
}

Some files were not shown because too many files have changed in this diff Show More