mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-05-04 15:07:43 +02:00
Merge branch 'ismail/5068_start_thread' into ismail/5068_design_tweaks
This commit is contained in:
@@ -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>
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
+25
@@ -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
|
||||
}
|
||||
}
|
||||
+25
@@ -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
Reference in New Issue
Block a user