mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-24 18:42:47 +02:00
Merge branch 'develop' into ismail/5096_thread_notifications
This commit is contained in:
@@ -18,6 +18,13 @@ import Foundation
|
||||
import MatrixSDK
|
||||
import Reusable
|
||||
import DGCollectionViewLeftAlignFlowLayout
|
||||
import UIKit
|
||||
|
||||
/// BubbleReactionsView items alignment
|
||||
enum BubbleReactionsViewAlignment {
|
||||
case left
|
||||
case right
|
||||
}
|
||||
|
||||
@objcMembers
|
||||
final class BubbleReactionsView: UIView, NibOwnerLoadable {
|
||||
@@ -51,6 +58,12 @@ final class BubbleReactionsView: UIView, NibOwnerLoadable {
|
||||
}
|
||||
}
|
||||
|
||||
var alignment: BubbleReactionsViewAlignment = .left {
|
||||
didSet {
|
||||
self.updateCollectionViewLayout(for: alignment)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
private func commonInit() {
|
||||
@@ -87,7 +100,18 @@ final class BubbleReactionsView: UIView, NibOwnerLoadable {
|
||||
self.collectionView.isScrollEnabled = false
|
||||
self.collectionView.delegate = self
|
||||
self.collectionView.dataSource = self
|
||||
self.collectionView.collectionViewLayout = DGCollectionViewLeftAlignFlowLayout()
|
||||
self.alignment = .left
|
||||
|
||||
self.collectionView.register(cellType: BubbleReactionViewCell.self)
|
||||
self.collectionView.register(cellType: BubbleReactionActionViewCell.self)
|
||||
self.collectionView.reloadData()
|
||||
}
|
||||
|
||||
private func updateCollectionViewLayout(for alignment: BubbleReactionsViewAlignment) {
|
||||
|
||||
let collectionViewLayout = self.collectionViewLayout(for: alignment)
|
||||
|
||||
self.collectionView.collectionViewLayout = collectionViewLayout
|
||||
|
||||
if let collectionViewFlowLayout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
|
||||
collectionViewFlowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
|
||||
@@ -95,9 +119,22 @@ final class BubbleReactionsView: UIView, NibOwnerLoadable {
|
||||
collectionViewFlowLayout.minimumLineSpacing = Constants.minimumLineSpacing
|
||||
}
|
||||
|
||||
self.collectionView.register(cellType: BubbleReactionViewCell.self)
|
||||
self.collectionView.register(cellType: BubbleReactionActionViewCell.self)
|
||||
self.collectionView.reloadData()
|
||||
self.collectionView.collectionViewLayout.invalidateLayout()
|
||||
}
|
||||
|
||||
private func collectionViewLayout(for alignment: BubbleReactionsViewAlignment) -> UICollectionViewLayout {
|
||||
|
||||
let collectionViewLayout: UICollectionViewLayout
|
||||
|
||||
switch alignment {
|
||||
case .left:
|
||||
collectionViewLayout = DGCollectionViewLeftAlignFlowLayout()
|
||||
case .right:
|
||||
collectionViewLayout = CollectionViewRightAlignFlowLayout()
|
||||
}
|
||||
|
||||
return collectionViewLayout
|
||||
}
|
||||
|
||||
private func setupLongPressGestureRecognizer() {
|
||||
|
||||
@@ -584,7 +584,7 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
|
||||
// Add vertical whitespace in case of a thread root
|
||||
additionalVerticalHeight+= [self threadSummaryViewHeightForEventId:eventId];
|
||||
// Add vertical whitespace in case of from a thread
|
||||
additionalVerticalHeight+= [self fromThreadViewHeightForEventId:eventId];
|
||||
additionalVerticalHeight+= [self fromAThreadViewHeightForEventId:eventId];
|
||||
// Add vertical whitespace in case of read receipts.
|
||||
additionalVerticalHeight+= [self readReceiptHeightForEventId:eventId];
|
||||
|
||||
@@ -605,7 +605,7 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
|
||||
height+= [self urlPreviewHeightForEventId:eventId];
|
||||
height+= [self reactionHeightForEventId:eventId];
|
||||
height+= [self threadSummaryViewHeightForEventId:eventId];
|
||||
height+= [self fromThreadViewHeightForEventId:eventId];
|
||||
height+= [self fromAThreadViewHeightForEventId:eventId];
|
||||
height+= [self readReceiptHeightForEventId:eventId];
|
||||
}
|
||||
|
||||
@@ -671,16 +671,16 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
|
||||
[ThreadSummaryView contentViewHeightForThread:component.thread fitting:self.maxTextViewWidth];
|
||||
}
|
||||
|
||||
- (CGFloat)fromThreadViewHeightForEventId:(NSString*)eventId
|
||||
- (CGFloat)fromAThreadViewHeightForEventId:(NSString*)eventId
|
||||
{
|
||||
if (!RiotSettings.shared.enableThreads)
|
||||
{
|
||||
// do not show from thread view if threads not enabled
|
||||
// do not show from a thread view if threads not enabled
|
||||
return 0;
|
||||
}
|
||||
if (roomDataSource.threadId)
|
||||
{
|
||||
// do not show from thread view on threads
|
||||
// do not show from a thread view on threads
|
||||
return 0;
|
||||
}
|
||||
NSInteger index = [self bubbleComponentIndexForEventId:eventId];
|
||||
@@ -694,8 +694,8 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
|
||||
// event is not in a thread
|
||||
return 0;
|
||||
}
|
||||
return RoomBubbleCellLayout.fromThreadViewTopMargin +
|
||||
[FromThreadView contentViewHeightForEvent:component.event fitting:self.maxTextViewWidth];
|
||||
return RoomBubbleCellLayout.fromAThreadViewTopMargin +
|
||||
[FromAThreadView contentViewHeightForEvent:component.event fitting:self.maxTextViewWidth];
|
||||
}
|
||||
|
||||
- (CGFloat)urlPreviewHeightForEventId:(NSString*)eventId
|
||||
@@ -907,6 +907,12 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat
|
||||
|
||||
- (BOOL)addEvent:(MXEvent*)event andRoomState:(MXRoomState*)roomState
|
||||
{
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
if (NO == [timelineConfiguration.currentStyle canAddEvent:event and:roomState to:self]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL shouldAddEvent = YES;
|
||||
|
||||
switch (self.tag)
|
||||
|
||||
@@ -118,14 +118,14 @@
|
||||
@protocol RoomDataSourceDelegate <MXKDataSourceDelegate>
|
||||
|
||||
/**
|
||||
Called when the room's encryption trust level did updated.
|
||||
Called when the room's encryption trust level did update.
|
||||
|
||||
@param roomDataSource room data source instance
|
||||
*/
|
||||
- (void)roomDataSourceDidUpdateEncryptionTrustLevel:(RoomDataSource * _Nonnull)roomDataSource;
|
||||
|
||||
/**
|
||||
Called when a thread summary view
|
||||
Called when a thread summary view is tapped.
|
||||
|
||||
@param roomDataSource room data source instance
|
||||
*/
|
||||
|
||||
@@ -383,6 +383,8 @@ const CGFloat kTypingCellHeight = 24;
|
||||
|
||||
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
|
||||
id<RoomTimelineCellDecorator> cellDecorator = [RoomTimelineConfiguration shared].currentStyle.cellDecorator;
|
||||
|
||||
// Finalize cell view customization here
|
||||
if ([cell isKindOfClass:MXKRoomBubbleTableViewCell.class])
|
||||
{
|
||||
@@ -394,11 +396,8 @@ const CGFloat kTypingCellHeight = 24;
|
||||
|
||||
BOOL isCollapsableCellCollapsed = cellData.collapsable && cellData.collapsed;
|
||||
|
||||
// Display timestamp of the last message
|
||||
if (cellData.containsLastMessage && !isCollapsableCellCollapsed)
|
||||
{
|
||||
[bubbleCell addTimestampLabelForComponent:cellData.mostRecentComponentIndex];
|
||||
}
|
||||
// Display timestamp of the message if needed
|
||||
[cellDecorator addTimestampLabelIfNeededToCell:bubbleCell cellData:cellData];
|
||||
|
||||
NSMutableArray *temporaryViews = [NSMutableArray new];
|
||||
|
||||
@@ -442,23 +441,8 @@ const CGFloat kTypingCellHeight = 24;
|
||||
urlPreviewView.tag = index;
|
||||
|
||||
[temporaryViews addObject:urlPreviewView];
|
||||
[bubbleCell.tmpSubviews addObject:urlPreviewView];
|
||||
|
||||
urlPreviewView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
urlPreviewView.availableWidth = cellData.maxTextViewWidth;
|
||||
[bubbleCell.contentView addSubview:urlPreviewView];
|
||||
|
||||
CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin;
|
||||
if (roomBubbleCellData.containsBubbleComponentWithEncryptionBadge)
|
||||
{
|
||||
leftMargin+= RoomBubbleCellLayout.encryptedContentLeftMargin;
|
||||
}
|
||||
|
||||
// Set the preview view's origin
|
||||
[NSLayoutConstraint activateConstraints: @[
|
||||
[urlPreviewView.leadingAnchor constraintEqualToAnchor:urlPreviewView.superview.leadingAnchor constant:leftMargin],
|
||||
[urlPreviewView.topAnchor constraintEqualToAnchor:urlPreviewView.superview.topAnchor constant:bottomPositionY + RoomBubbleCellLayout.urlPreviewViewTopMargin + RoomBubbleCellLayout.reactionsViewTopMargin],
|
||||
]];
|
||||
[cellDecorator addURLPreviewView:urlPreviewView
|
||||
toCell:bubbleCell cellData:cellData contentViewPositionY:bottomPositionY];
|
||||
}
|
||||
|
||||
MXAggregatedReactions* reactions = cellData.reactions[componentEventId].aggregatedReactionsWithNonZeroCount;
|
||||
@@ -480,44 +464,8 @@ const CGFloat kTypingCellHeight = 24;
|
||||
bubbleReactionsViewModel.viewModelDelegate = self;
|
||||
|
||||
[temporaryViews addObject:reactionsView];
|
||||
[bubbleCell.tmpSubviews addObject:reactionsView];
|
||||
|
||||
if ([[bubbleCell class] conformsToProtocol:@protocol(BubbleCellReactionsDisplayable)])
|
||||
{
|
||||
id<BubbleCellReactionsDisplayable> reactionsDisplayable = (id<BubbleCellReactionsDisplayable>)bubbleCell;
|
||||
[reactionsDisplayable addReactionsView:reactionsView];
|
||||
}
|
||||
else
|
||||
{
|
||||
reactionsView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[bubbleCell.contentView addSubview:reactionsView];
|
||||
|
||||
CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin;
|
||||
|
||||
if (roomBubbleCellData.containsBubbleComponentWithEncryptionBadge)
|
||||
{
|
||||
leftMargin+= RoomBubbleCellLayout.encryptedContentLeftMargin;
|
||||
}
|
||||
|
||||
// The top constraint may need to include the URL preview view
|
||||
NSLayoutConstraint *topConstraint;
|
||||
if (urlPreviewView)
|
||||
{
|
||||
topConstraint = [reactionsView.topAnchor constraintEqualToAnchor:urlPreviewView.bottomAnchor constant:RoomBubbleCellLayout.reactionsViewTopMargin];
|
||||
}
|
||||
else
|
||||
{
|
||||
topConstraint = [reactionsView.topAnchor constraintEqualToAnchor:reactionsView.superview.topAnchor constant:bottomPositionY + RoomBubbleCellLayout.reactionsViewTopMargin];
|
||||
}
|
||||
|
||||
// Force receipts container size
|
||||
[NSLayoutConstraint activateConstraints:
|
||||
@[
|
||||
[reactionsView.leadingAnchor constraintEqualToAnchor:reactionsView.superview.leadingAnchor constant:leftMargin],
|
||||
[reactionsView.trailingAnchor constraintEqualToAnchor:reactionsView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin],
|
||||
topConstraint
|
||||
]];
|
||||
}
|
||||
[cellDecorator addReactionView:reactionsView toCell:bubbleCell
|
||||
cellData:cellData contentViewPositionY:bottomPositionY upperDecorationView:urlPreviewView];
|
||||
}
|
||||
|
||||
ThreadSummaryView *threadSummaryView;
|
||||
@@ -527,55 +475,16 @@ const CGFloat kTypingCellHeight = 24;
|
||||
{
|
||||
threadSummaryView = [[ThreadSummaryView alloc] initWithThread:component.thread];
|
||||
threadSummaryView.delegate = self;
|
||||
|
||||
threadSummaryView.tag = index;
|
||||
|
||||
[temporaryViews addObject:threadSummaryView];
|
||||
[bubbleCell.tmpSubviews addObject:threadSummaryView];
|
||||
UIView *upperDecorationView = reactionsView ?: urlPreviewView;
|
||||
|
||||
threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
|
||||
if ([[bubbleCell class] conformsToProtocol:@protocol(BubbleCellThreadSummaryDisplayable)])
|
||||
{
|
||||
id<BubbleCellThreadSummaryDisplayable> threadSummaryDisplayable = (id<BubbleCellThreadSummaryDisplayable>)bubbleCell;
|
||||
|
||||
[threadSummaryDisplayable addThreadSummaryView:threadSummaryView];
|
||||
}
|
||||
else
|
||||
{
|
||||
[bubbleCell.contentView addSubview:threadSummaryView];
|
||||
|
||||
CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin;
|
||||
if (roomBubbleCellData.containsBubbleComponentWithEncryptionBadge)
|
||||
{
|
||||
leftMargin+= RoomBubbleCellLayout.encryptedContentLeftMargin;
|
||||
}
|
||||
|
||||
// The top constraint may need to include the URL preview view or reactions view
|
||||
NSLayoutConstraint *topConstraint;
|
||||
if (reactionsView)
|
||||
{
|
||||
topConstraint = [threadSummaryView.topAnchor constraintEqualToAnchor:reactionsView.bottomAnchor
|
||||
constant:RoomBubbleCellLayout.threadSummaryViewTopMargin];
|
||||
}
|
||||
else if (urlPreviewView)
|
||||
{
|
||||
topConstraint = [threadSummaryView.topAnchor constraintEqualToAnchor:urlPreviewView.bottomAnchor
|
||||
constant:RoomBubbleCellLayout.threadSummaryViewTopMargin];
|
||||
}
|
||||
else
|
||||
{
|
||||
topConstraint = [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor
|
||||
constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin];
|
||||
}
|
||||
|
||||
// Set constraints for the summary view
|
||||
[NSLayoutConstraint activateConstraints: @[
|
||||
[threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor
|
||||
constant:leftMargin],
|
||||
topConstraint,
|
||||
[threadSummaryView.heightAnchor constraintEqualToConstant:[ThreadSummaryView contentViewHeightForThread:component.thread fitting:cellData.maxTextViewWidth]],
|
||||
[threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin]
|
||||
]];
|
||||
}
|
||||
[cellDecorator addThreadSummaryView:threadSummaryView
|
||||
toCell:bubbleCell
|
||||
cellData:cellData
|
||||
contentViewPositionY:bottomPositionY
|
||||
upperDecorationView:upperDecorationView];
|
||||
}
|
||||
|
||||
MXKReceiptSendersContainer* avatarsContainer;
|
||||
@@ -633,67 +542,13 @@ const CGFloat kTypingCellHeight = 24;
|
||||
avatarsContainer.accessibilityIdentifier = @"readReceiptsContainer";
|
||||
|
||||
[temporaryViews addObject:avatarsContainer];
|
||||
// Add this read receipts container in the content view
|
||||
[bubbleCell.tmpSubviews addObject:avatarsContainer];
|
||||
UIView *upperDecorationView = threadSummaryView ?: (reactionsView ?: urlPreviewView);
|
||||
|
||||
if ([[bubbleCell class] conformsToProtocol:@protocol(BubbleCellReadReceiptsDisplayable)])
|
||||
{
|
||||
id<BubbleCellReadReceiptsDisplayable> readReceiptsDisplayable = (id<BubbleCellReadReceiptsDisplayable>)bubbleCell;
|
||||
|
||||
[readReceiptsDisplayable addReadReceiptsView:avatarsContainer];
|
||||
}
|
||||
else
|
||||
{
|
||||
[bubbleCell.contentView addSubview:avatarsContainer];
|
||||
|
||||
// Force receipts container size
|
||||
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
|
||||
attribute:NSLayoutAttributeWidth
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:RoomBubbleCellLayout.readReceiptsViewWidth];
|
||||
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
|
||||
attribute:NSLayoutAttributeHeight
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:RoomBubbleCellLayout.readReceiptsViewHeight];
|
||||
|
||||
// Force receipts container position
|
||||
NSLayoutConstraint *trailingConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:avatarsContainer.superview
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
multiplier:1.0
|
||||
constant:-RoomBubbleCellLayout.readReceiptsViewRightMargin];
|
||||
|
||||
// At the bottom, we either have a thread summary, a reactions, a URL preview or nothing
|
||||
NSLayoutConstraint *topConstraint;
|
||||
if (threadSummaryView)
|
||||
{
|
||||
topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:threadSummaryView.bottomAnchor constant:RoomBubbleCellLayout.readReceiptsViewTopMargin];
|
||||
}
|
||||
else if (reactionsView)
|
||||
{
|
||||
topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:reactionsView.bottomAnchor constant:RoomBubbleCellLayout.readReceiptsViewTopMargin];
|
||||
}
|
||||
else if (urlPreviewView)
|
||||
{
|
||||
topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:urlPreviewView.bottomAnchor constant:RoomBubbleCellLayout.readReceiptsViewTopMargin];
|
||||
}
|
||||
else
|
||||
{
|
||||
topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:avatarsContainer.superview.topAnchor constant:bottomPositionY + RoomBubbleCellLayout.readReceiptsViewTopMargin];
|
||||
}
|
||||
|
||||
|
||||
// Available on iOS 8 and later
|
||||
[NSLayoutConstraint activateConstraints:@[widthConstraint, heightConstraint, topConstraint, trailingConstraint]];
|
||||
}
|
||||
[cellDecorator addReadReceiptsView:avatarsContainer
|
||||
toCell:bubbleCell
|
||||
cellData:cellData
|
||||
contentViewPositionY:bottomPositionY
|
||||
upperDecorationView:upperDecorationView];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,16 +631,7 @@ const CGFloat kTypingCellHeight = 24;
|
||||
// Check whether an event is currently selected: the other messages are then blurred
|
||||
if (_selectedEventId)
|
||||
{
|
||||
// Check whether the selected event belongs to this bubble
|
||||
NSInteger selectedComponentIndex = cellData.selectedComponentIndex;
|
||||
if (selectedComponentIndex != NSNotFound)
|
||||
{
|
||||
[bubbleCell selectComponent:cellData.selectedComponentIndex showEditButton:NO showTimestamp:cellData.showTimestampForSelectedComponent];
|
||||
}
|
||||
else
|
||||
{
|
||||
bubbleCell.blurred = YES;
|
||||
}
|
||||
[[RoomTimelineConfiguration shared].currentStyle applySelectedStyleIfNeededToCell:bubbleCell cellData:cellData];
|
||||
}
|
||||
|
||||
// Reset the marker if any
|
||||
@@ -822,13 +668,24 @@ const CGFloat kTypingCellHeight = 24;
|
||||
// We are interested only by outgoing messages
|
||||
if ([cellData.senderId isEqualToString: self.mxSession.credentials.userId])
|
||||
{
|
||||
[bubbleCell updateTickViewWithFailedEventIds:self.failedEventIds];
|
||||
[cellDecorator addSendStatusViewToCell:bubbleCell
|
||||
withFailedEventIds:self.failedEventIds];
|
||||
}
|
||||
|
||||
// Make extra cell layout updates if needed
|
||||
[self updateCellLayoutIfNeeded:bubbleCell withCellData:cellData];
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)updateCellLayoutIfNeeded:(MXKRoomBubbleTableViewCell*)cell withCellData:(MXKRoomBubbleCellData*)cellData {
|
||||
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
[timelineConfiguration.currentStyle.cellLayoutUpdater updateLayoutIfNeededFor:cell andCellData:cellData];
|
||||
}
|
||||
|
||||
- (RoomBubbleCellData*)roomBubbleCellDataForEventId:(NSString*)eventId
|
||||
{
|
||||
id<MXKRoomBubbleCellDataStoring> cellData = [self cellDataOfEventWithEventId:eventId];
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import UIKit
|
||||
import Reusable
|
||||
import Mapbox
|
||||
|
||||
class LocationUserMarkerView: MGLAnnotationView, NibLoadable {
|
||||
class LocationMarkerView: MGLAnnotationView, NibLoadable {
|
||||
|
||||
@IBOutlet private var avatarView: UserAvatarView!
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<?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="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" insetsLayoutMarginsFromSafeArea="NO" id="iN0-l3-epB" customClass="LocationMarkerView" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="108"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GS1-Cw-Ezx">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="54"/>
|
||||
<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"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="50" id="41S-fj-tn4"/>
|
||||
<constraint firstAttribute="height" constant="54" id="MAX-5E-xvS"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="location_marker_icon" translatesAutoresizingMaskIntoConstraints="NO" id="gQe-Hv-22e">
|
||||
<rect key="frame" x="13" y="15" width="24" height="24"/>
|
||||
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="24" id="XuF-VU-qG2"/>
|
||||
<constraint firstAttribute="height" constant="24" id="ejE-pC-umv"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qut-wn-BX3" customClass="UserAvatarView" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="2" y="2" width="46" height="46"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="46" id="BjG-I5-n8f"/>
|
||||
<constraint firstAttribute="width" constant="46" id="W3F-Aw-FO3"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="ldO-kc-R5W" firstAttribute="top" secondItem="GS1-Cw-Ezx" secondAttribute="top" id="1cb-YG-bcI"/>
|
||||
<constraint firstItem="ldO-kc-R5W" firstAttribute="leading" secondItem="GS1-Cw-Ezx" secondAttribute="leading" id="8I8-Zn-R5S"/>
|
||||
<constraint firstItem="gQe-Hv-22e" firstAttribute="centerY" secondItem="GS1-Cw-Ezx" secondAttribute="centerY" id="EE9-rM-y0V"/>
|
||||
<constraint firstItem="qut-wn-BX3" firstAttribute="centerY" secondItem="GS1-Cw-Ezx" secondAttribute="centerY" constant="-2" id="EQM-Hr-37h"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ldO-kc-R5W" secondAttribute="trailing" id="QUB-rY-t4j"/>
|
||||
<constraint firstItem="qut-wn-BX3" firstAttribute="centerX" secondItem="GS1-Cw-Ezx" secondAttribute="centerX" id="XLg-Qs-yTR"/>
|
||||
<constraint firstAttribute="bottom" secondItem="ldO-kc-R5W" secondAttribute="bottom" id="l4H-nN-44g"/>
|
||||
<constraint firstItem="gQe-Hv-22e" firstAttribute="centerX" secondItem="GS1-Cw-Ezx" secondAttribute="centerX" id="syG-Kp-4F9"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="GS1-Cw-Ezx" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="61F-Ve-exC"/>
|
||||
<constraint firstAttribute="trailing" secondItem="GS1-Cw-Ezx" secondAttribute="trailing" id="H8I-4T-A0M"/>
|
||||
<constraint firstItem="GS1-Cw-Ezx" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="hhI-gR-E5z"/>
|
||||
<constraint firstAttribute="bottom" secondItem="GS1-Cw-Ezx" secondAttribute="bottom" constant="54" id="mvD-6W-gMh"/>
|
||||
</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="58.695652173913047" y="4.6875"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="location_marker_icon" width="24" height="24"/>
|
||||
<image name="location_user_marker" width="51" height="54.5"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -1,46 +0,0 @@
|
||||
<?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>
|
||||
@@ -17,7 +17,6 @@
|
||||
import UIKit
|
||||
import Reusable
|
||||
import Mapbox
|
||||
import Keys
|
||||
|
||||
class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegate {
|
||||
|
||||
@@ -25,7 +24,6 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
||||
|
||||
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
|
||||
@@ -36,9 +34,10 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
||||
|
||||
@IBOutlet private var descriptionContainerView: UIView!
|
||||
@IBOutlet private var descriptionLabel: UILabel!
|
||||
@IBOutlet private var descriptionIcon: UIImageView!
|
||||
|
||||
private var mapView: MGLMapView!
|
||||
private var annotationView: LocationUserMarkerView?
|
||||
private var annotationView: LocationMarkerView?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
@@ -73,19 +72,13 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
public func displayLocation(_ location: CLLocationCoordinate2D,
|
||||
userIdentifier: String,
|
||||
userDisplayName: String,
|
||||
userAvatarURLString: String?,
|
||||
mediaManager: MXMediaManager) {
|
||||
|
||||
annotationView = LocationUserMarkerView.loadFromNib()
|
||||
public func displayLocation(_ location: CLLocationCoordinate2D, userAvatarData: AvatarViewData? = nil) {
|
||||
|
||||
annotationView?.setAvatarData(AvatarViewData(matrixItemId: userIdentifier,
|
||||
displayName: userDisplayName,
|
||||
avatarUrl: userAvatarURLString,
|
||||
mediaManager: mediaManager,
|
||||
fallbackImage: .matrixItem(userIdentifier, userDisplayName)))
|
||||
annotationView = LocationMarkerView.loadFromNib()
|
||||
|
||||
if let userAvatarData = userAvatarData {
|
||||
annotationView?.setAvatarData(userAvatarData)
|
||||
}
|
||||
|
||||
if let annotations = mapView.annotations {
|
||||
mapView.removeAnnotations(annotations)
|
||||
@@ -103,6 +96,7 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
||||
func update(theme: Theme) {
|
||||
descriptionLabel.textColor = theme.colors.primaryContent
|
||||
descriptionLabel.font = theme.fonts.footnote
|
||||
descriptionIcon.tintColor = theme.colors.accent
|
||||
layer.borderColor = theme.colors.quinaryContent.cgColor
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<connections>
|
||||
<outlet property="descriptionContainerView" destination="oVd-gS-Rmb" id="Npu-jp-oYo"/>
|
||||
<outlet property="descriptionIcon" destination="GP2-dA-giJ" id="7YL-UU-ClT"/>
|
||||
<outlet property="descriptionLabel" destination="c68-l7-McA" id="HiH-8Q-yTp"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="165.94202898550725" y="-100.78125"/>
|
||||
|
||||
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
Copyright 2019 The Matrix.org Foundation C.I.C
|
||||
|
||||
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 <MatrixSDK/MatrixSDK.h>
|
||||
|
||||
#import "MXKViewController.h"
|
||||
#import "MXKRoomDataSource.h"
|
||||
#import "MXKRoomTitleView.h"
|
||||
#import "MXKRoomInputToolbarView.h"
|
||||
#import "MXKRoomActivitiesView.h"
|
||||
#import "MXKEventDetailsView.h"
|
||||
|
||||
#import "MXKAttachmentsViewController.h"
|
||||
#import "MXKAttachmentAnimator.h"
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MXKRoomViewControllerJoinRoomResult) {
|
||||
MXKRoomViewControllerJoinRoomResultSuccess,
|
||||
MXKRoomViewControllerJoinRoomResultFailureRoomEmpty,
|
||||
MXKRoomViewControllerJoinRoomResultFailureJoinInProgress,
|
||||
MXKRoomViewControllerJoinRoomResultFailureGeneric
|
||||
};
|
||||
|
||||
/**
|
||||
This view controller displays messages of a room. Only one matrix session is handled by this view controller.
|
||||
*/
|
||||
@interface MXKRoomViewController : MXKViewController <MXKDataSourceDelegate, MXKRoomTitleViewDelegate, MXKRoomInputToolbarViewDelegate, UITableViewDelegate, UIDocumentInteractionControllerDelegate, MXKAttachmentsViewControllerDelegate, MXKRoomActivitiesViewDelegate, MXKSourceAttachmentAnimatorDelegate>
|
||||
{
|
||||
@protected
|
||||
/**
|
||||
The identifier of the current event displayed at the bottom of the table (just above the toolbar).
|
||||
Use to anchor the message displayed at the bottom during table refresh.
|
||||
*/
|
||||
NSString *currentEventIdAtTableBottom;
|
||||
|
||||
/**
|
||||
Boolean value used to scroll to bottom the bubble history after refresh.
|
||||
*/
|
||||
BOOL shouldScrollToBottomOnTableRefresh;
|
||||
|
||||
/**
|
||||
Potential event details view.
|
||||
*/
|
||||
__weak MXKEventDetailsView *eventDetailsView;
|
||||
|
||||
/**
|
||||
Current alert (if any).
|
||||
*/
|
||||
__weak UIAlertController *currentAlert;
|
||||
|
||||
/**
|
||||
The document interaction Controller used to share attachment
|
||||
*/
|
||||
UIDocumentInteractionController *documentInteractionController;
|
||||
|
||||
/**
|
||||
The current shared attachment.
|
||||
*/
|
||||
MXKAttachment *currentSharedAttachment;
|
||||
|
||||
/**
|
||||
The potential text input placeholder is saved when it is replaced temporarily
|
||||
*/
|
||||
NSString *savedInputToolbarPlaceholder;
|
||||
|
||||
/**
|
||||
Tell whether the input toolbar required to run an animation indicator.
|
||||
*/
|
||||
BOOL isInputToolbarProcessing;
|
||||
|
||||
/**
|
||||
Tell whether a device rotation is in progress
|
||||
*/
|
||||
BOOL isSizeTransitionInProgress;
|
||||
|
||||
/**
|
||||
The current visibility of the status bar in this view controller.
|
||||
*/
|
||||
BOOL isStatusBarHidden;
|
||||
|
||||
/**
|
||||
YES to prevent `bubblesTableView` scrolling when calling -[setBubbleTableViewContentOffset:animated:]
|
||||
*/
|
||||
BOOL preventBubblesTableViewScroll;
|
||||
}
|
||||
|
||||
/**
|
||||
The current data source associated to the view controller.
|
||||
*/
|
||||
@property (nonatomic, readonly) MXKRoomDataSource *roomDataSource;
|
||||
|
||||
/**
|
||||
Flag indicating if this instance has the memory ownership of its `roomDataSource`.
|
||||
If YES, it will release it on [self destroy] call;
|
||||
Default is NO.
|
||||
*/
|
||||
@property (nonatomic) BOOL hasRoomDataSourceOwnership;
|
||||
|
||||
/**
|
||||
Tell whether the bubbles table view display is in transition. Its display is not warranty during the transition.
|
||||
*/
|
||||
@property (nonatomic, getter=isBubbleTableViewDisplayInTransition) BOOL bubbleTableViewDisplayInTransition;
|
||||
|
||||
/**
|
||||
Tell whether the automatic events acknowledgement (based on read receipt) is enabled.
|
||||
Default is YES.
|
||||
*/
|
||||
@property (nonatomic, getter=isEventsAcknowledgementEnabled) BOOL eventsAcknowledgementEnabled;
|
||||
|
||||
/**
|
||||
Tell whether the room read marker must be updated when an event is acknowledged with a read receipt.
|
||||
Default is NO.
|
||||
*/
|
||||
@property (nonatomic) BOOL updateRoomReadMarker;
|
||||
|
||||
/**
|
||||
When the room view controller displays a room data source based on a timeline with an initial event,
|
||||
the bubble table view content is scrolled by default to display the top of this event at the center of the screen
|
||||
the first time it appears.
|
||||
Use this property to force the table view to center its content on the bottom part of the event.
|
||||
Default is NO.
|
||||
*/
|
||||
@property (nonatomic) BOOL centerBubblesTableViewContentOnTheInitialEventBottom;
|
||||
|
||||
/**
|
||||
The current title view defined into the view controller.
|
||||
*/
|
||||
@property (nonatomic, weak, readonly) MXKRoomTitleView* titleView;
|
||||
|
||||
/**
|
||||
The current input toolbar view defined into the view controller.
|
||||
*/
|
||||
@property (nonatomic, weak, readonly) MXKRoomInputToolbarView* inputToolbarView;
|
||||
|
||||
/**
|
||||
The current extra info view defined into the view controller.
|
||||
*/
|
||||
@property (nonatomic, readonly) MXKRoomActivitiesView* activitiesView;
|
||||
|
||||
/**
|
||||
The threshold used to trigger inconspicuous back pagination, or forwards pagination
|
||||
for non live timeline. A pagination is triggered when the vertical content offset
|
||||
is lower this threshold.
|
||||
Default is 300.
|
||||
*/
|
||||
@property (nonatomic) NSUInteger paginationThreshold;
|
||||
|
||||
/**
|
||||
The maximum number of messages to retrieve during a pagination. Default is 30.
|
||||
*/
|
||||
@property (nonatomic) NSUInteger paginationLimit;
|
||||
|
||||
/**
|
||||
Enable/disable saving of the current typed text in message composer when view disappears.
|
||||
The message composer is prefilled with this text when the room is opened again.
|
||||
This property value is YES by default.
|
||||
*/
|
||||
@property BOOL saveProgressTextInput;
|
||||
|
||||
/**
|
||||
The invited rooms can be automatically joined when the data source is ready.
|
||||
This property enable/disable this option. Its value is YES by default.
|
||||
*/
|
||||
@property BOOL autoJoinInvitedRoom;
|
||||
|
||||
/**
|
||||
Tell whether the room history is automatically scrolled to the most recent messages
|
||||
when a keyboard is presented. YES by default.
|
||||
This option is ignored when an alert is presented.
|
||||
*/
|
||||
@property BOOL scrollHistoryToTheBottomOnKeyboardPresentation;
|
||||
|
||||
/**
|
||||
YES (default) to show actions button in document preview. NO otherwise.
|
||||
*/
|
||||
@property BOOL allowActionsInDocumentPreview;
|
||||
|
||||
/**
|
||||
Duration of the animation in case of the composer needs to be resized (default 0.3s)
|
||||
*/
|
||||
@property NSTimeInterval resizeComposerAnimationDuration;
|
||||
|
||||
/**
|
||||
This object is defined when the displayed room is left. It is added into the bubbles table header.
|
||||
This label is used to display the reason why the room has been left.
|
||||
*/
|
||||
@property (nonatomic, weak, readonly) UILabel *leftRoomReasonLabel;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UITableView *bubblesTableView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *roomTitleViewContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *roomInputToolbarContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *roomActivitiesContainer;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bubblesTableViewTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bubblesTableViewBottomConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *roomActivitiesContainerHeightConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *roomInputToolbarContainerHeightConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *roomInputToolbarContainerBottomConstraint;
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
/**
|
||||
Returns the `UINib` object initialized for a `MXKRoomViewController`.
|
||||
|
||||
@return The initialized `UINib` object or `nil` if there were errors during initialization
|
||||
or the nib file could not be located.
|
||||
|
||||
@discussion You may override this method to provide a customized nib. If you do,
|
||||
you should also override `roomViewController` to return your
|
||||
view controller loaded from your custom nib.
|
||||
*/
|
||||
+ (UINib *)nib;
|
||||
|
||||
/**
|
||||
Creates and returns a new `MXKRoomViewController` object.
|
||||
|
||||
@discussion This is the designated initializer for programmatic instantiation.
|
||||
@return An initialized `MXKRoomViewController` object if successful, `nil` otherwise.
|
||||
*/
|
||||
+ (instancetype)roomViewController;
|
||||
|
||||
/**
|
||||
Display a room.
|
||||
|
||||
@param dataSource the data source .
|
||||
*/
|
||||
- (void)displayRoom:(MXKRoomDataSource*)dataSource;
|
||||
|
||||
/**
|
||||
This method is called when the associated data source is ready.
|
||||
|
||||
By default this operation triggers the initial back pagination when the user is an actual
|
||||
member of the room (membership = join).
|
||||
|
||||
The invited rooms are automatically joined during this operation if 'autoJoinInvitedRoom' is YES.
|
||||
When the room is successfully joined, an initial back pagination is triggered too.
|
||||
Else nothing is done for the invited rooms.
|
||||
|
||||
Override it to customize the view controller behavior when the data source is ready.
|
||||
*/
|
||||
- (void)onRoomDataSourceReady;
|
||||
|
||||
/**
|
||||
Update view controller appearance according to the state of its associated data source.
|
||||
This method is called in the following use cases:
|
||||
- on data source change (see `[MXKRoomViewController displayRoom:]`).
|
||||
- on data source state change (see `[MXKDataSourceDelegate dataSource:didStateChange:]`)
|
||||
- when view did appear.
|
||||
|
||||
The default implementation:
|
||||
- show input toolbar view if the dataSource is defined and ready (`MXKDataSourceStateReady`), hide toolbar in others use cases.
|
||||
- stop activity indicator if the dataSource is defined and ready (`MXKDataSourceStateReady`).
|
||||
- update view controller title with room information.
|
||||
|
||||
Override it to customize view appearance according to data source state.
|
||||
*/
|
||||
- (void)updateViewControllerAppearanceOnRoomDataSourceState;
|
||||
|
||||
/**
|
||||
This method is called when the associated data source has encountered an error on the timeline.
|
||||
|
||||
Override it to customize the view controller behavior.
|
||||
|
||||
@param notif the notification data sent with kMXKRoomDataSourceTimelineError notif.
|
||||
*/
|
||||
- (void)onTimelineError:(NSNotification *)notif;
|
||||
|
||||
/**
|
||||
Join the current displayed room.
|
||||
|
||||
This operation fails if the user has already joined the room, or if the data source is not ready.
|
||||
It fails if a join request is already running too.
|
||||
|
||||
@param completion the block to execute at the end of the operation.
|
||||
You may specify nil for this parameter.
|
||||
*/
|
||||
- (void)joinRoom:(void(^)(MXKRoomViewControllerJoinRoomResult result))completion;
|
||||
|
||||
/**
|
||||
Join a room with a room id or an alias.
|
||||
|
||||
This operation fails if the user has already joined the room, or if the data source is not ready,
|
||||
or if the access to the room is forbidden to the user.
|
||||
It fails if a join request is already running too.
|
||||
|
||||
@param roomIdOrAlias the id or the alias of the room to join.
|
||||
@param viaServers The server names to try and join through in addition to those that are automatically chosen. It is optional and can be nil.
|
||||
@param signUrl the signurl paramater passed with a 3PID invitation. It is optional and can be nil.
|
||||
|
||||
@param completion the block to execute at the end of the operation.
|
||||
You may specify nil for this parameter.
|
||||
*/
|
||||
- (void)joinRoomWithRoomIdOrAlias:(NSString*)roomIdOrAlias
|
||||
viaServers:(NSArray<NSString*>*)viaServers
|
||||
andSignUrl:(NSString*)signUrl
|
||||
completion:(void(^)(MXKRoomViewControllerJoinRoomResult result))completion;
|
||||
|
||||
/**
|
||||
Update view controller appearance when the user is about to leave the displayed room.
|
||||
This method is called when the user will leave the current room (see `kMXSessionWillLeaveRoomNotification`).
|
||||
|
||||
The default implementation:
|
||||
- discard `roomDataSource`
|
||||
- hide input toolbar view
|
||||
- freeze the room title display
|
||||
- add a label (`leftRoomReasonLabel`) in bubbles table header to display the reason why the room has been left.
|
||||
|
||||
Override it to customize view appearance, or to withdraw the view controller.
|
||||
|
||||
@param event the MXEvent responsible for the leaving.
|
||||
*/
|
||||
- (void)leaveRoomOnEvent:(MXEvent*)event;
|
||||
|
||||
/**
|
||||
Register the class used to instantiate the title view which will handle the room name display.
|
||||
|
||||
The resulting view is added into 'roomTitleViewContainer' view, which must be defined before calling this method.
|
||||
|
||||
Note: By default the room name is displayed by using 'navigationItem.title' field of the view controller.
|
||||
|
||||
@param roomTitleViewClass a MXKRoomTitleView-inherited class.
|
||||
*/
|
||||
- (void)setRoomTitleViewClass:(Class)roomTitleViewClass;
|
||||
|
||||
/**
|
||||
Register the class used to instantiate the input toolbar view which will handle message composer
|
||||
and attachments selection for the room.
|
||||
|
||||
The resulting view is added into 'roomInputToolbarContainer' view, which must be defined before calling this method.
|
||||
|
||||
@param roomInputToolbarViewClass a MXKRoomInputToolbarView-inherited class, or nil to remove the current view.
|
||||
*/
|
||||
- (void)setRoomInputToolbarViewClass:(Class)roomInputToolbarViewClass;
|
||||
|
||||
/**
|
||||
Register the class used to instantiate the extra info view.
|
||||
|
||||
The resulting view is added into 'roomActivitiesContainer' view, which must be defined before calling this method.
|
||||
|
||||
@param roomActivitiesViewClass a MXKRoomActivitiesViewClass-inherited class, or nil to remove the current view.
|
||||
*/
|
||||
- (void)setRoomActivitiesViewClass:(Class)roomActivitiesViewClass;
|
||||
|
||||
/**
|
||||
Register the class used to instantiate the viewer dedicated to the attachments with thumbnail.
|
||||
By default 'MXKAttachmentsViewController' class is used.
|
||||
|
||||
@param attachmentsViewerClass a MXKAttachmentsViewController-inherited class, or nil to restore the default class.
|
||||
*/
|
||||
- (void)setAttachmentsViewerClass:(Class)attachmentsViewerClass;
|
||||
|
||||
/**
|
||||
Register the view class used to display the details of an event.
|
||||
MXKEventDetailsView is used by default.
|
||||
|
||||
@param eventDetailsViewClass a MXKEventDetailsView-inherited class.
|
||||
*/
|
||||
- (void)setEventDetailsViewClass:(Class)eventDetailsViewClass;
|
||||
|
||||
/**
|
||||
Detect and process potential IRC command in provided string.
|
||||
|
||||
@param string to analyse
|
||||
@return YES if IRC style command has been detected and interpreted.
|
||||
*/
|
||||
- (BOOL)isIRCStyleCommand:(NSString*)string;
|
||||
|
||||
/**
|
||||
Mention the member display name in the current text of the message composer.
|
||||
The message composer becomes then the first responder.
|
||||
*/
|
||||
- (void)mention:(MXRoomMember*)roomMember;
|
||||
|
||||
/**
|
||||
Force to dismiss keyboard if any
|
||||
*/
|
||||
- (void)dismissKeyboard;
|
||||
|
||||
/**
|
||||
Tell whether the most recent message of the room history is visible.
|
||||
*/
|
||||
- (BOOL)isBubblesTableScrollViewAtTheBottom;
|
||||
|
||||
/**
|
||||
Scroll the room history until the most recent message.
|
||||
*/
|
||||
- (void)scrollBubblesTableViewToBottomAnimated:(BOOL)animated;
|
||||
|
||||
/**
|
||||
Dismiss the keyboard and all the potential subviews.
|
||||
*/
|
||||
- (void)dismissTemporarySubViews;
|
||||
|
||||
/**
|
||||
Display a popup with the event detais.
|
||||
|
||||
@param event the event to inspect.
|
||||
*/
|
||||
- (void)showEventDetails:(MXEvent *)event;
|
||||
|
||||
/**
|
||||
Present the attachments viewer by displaying the attachment of the provided cell.
|
||||
|
||||
@param cell the table view cell with attachment
|
||||
*/
|
||||
- (void)showAttachmentInCell:(UITableViewCell*)cell;
|
||||
|
||||
/**
|
||||
Force a refresh of the room history display.
|
||||
|
||||
You should not call this method directly.
|
||||
You may override it in inherited 'MXKRoomViewController' class.
|
||||
|
||||
@param useBottomAnchor tells whether the updated history must keep display the same event at the bottom.
|
||||
@return a boolean value which tells whether the table has been scrolled to the bottom.
|
||||
*/
|
||||
- (BOOL)reloadBubblesTable:(BOOL)useBottomAnchor;
|
||||
|
||||
/**
|
||||
Sets the offset from the content `bubblesTableView`'s origin. Take into account `preventBubblesTableViewScroll` value.
|
||||
|
||||
@param contentOffset Offset from the content `bubblesTableView`’s origin.
|
||||
@param animated YES to animate the transition.
|
||||
*/
|
||||
- (void)setBubbleTableViewContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;
|
||||
|
||||
/**
|
||||
Handle typing notification.
|
||||
|
||||
@param typing Flag indicating whether the user is typing or not.
|
||||
*/
|
||||
- (void)handleTypingNotification:(BOOL)typing;
|
||||
|
||||
@end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MXKRoomViewController">
|
||||
<connections>
|
||||
<outlet property="bubblesTableView" destination="BGD-sd-SQR" id="OG4-Tw-Ovt"/>
|
||||
<outlet property="bubblesTableViewBottomConstraint" destination="Ksk-39-kfi" id="CTo-Ux-4NP"/>
|
||||
<outlet property="bubblesTableViewTopConstraint" destination="X14-4s-uGM" id="Hic-6h-N05"/>
|
||||
<outlet property="roomActivitiesContainer" destination="XX4-n6-hCm" id="uD0-ab-8s8"/>
|
||||
<outlet property="roomActivitiesContainerHeightConstraint" destination="E8v-l2-8eV" id="ebD-oV-ttx"/>
|
||||
<outlet property="roomInputToolbarContainer" destination="nLd-BP-JAE" id="1dp-P1-0js"/>
|
||||
<outlet property="roomInputToolbarContainerBottomConstraint" destination="kQ6-Cg-FMi" id="nHr-fR-XnV"/>
|
||||
<outlet property="roomInputToolbarContainerHeightConstraint" destination="5eD-Fm-RDb" id="6ny-5w-1UA"/>
|
||||
<outlet property="view" destination="iN0-l3-epB" id="ieV-u7-rXU"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="interactive" style="plain" separatorStyle="none" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="BGD-sd-SQR">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="626"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</tableView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XX4-n6-hCm" userLabel="Activities Container">
|
||||
<rect key="frame" x="0.0" y="606" width="375" height="20"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="E8v-l2-8eV"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nLd-BP-JAE" userLabel="Room Input Toolbar Container">
|
||||
<rect key="frame" x="0.0" y="626" width="375" height="41"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="41" id="5eD-Fm-RDb"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="BGD-sd-SQR" secondAttribute="trailing" id="0la-ok-MBr"/>
|
||||
<constraint firstItem="nLd-BP-JAE" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="4Q7-hr-rqi"/>
|
||||
<constraint firstAttribute="bottom" secondItem="BGD-sd-SQR" secondAttribute="bottom" constant="41" id="Ksk-39-kfi"/>
|
||||
<constraint firstItem="XX4-n6-hCm" firstAttribute="bottom" secondItem="nLd-BP-JAE" secondAttribute="top" id="QO8-nF-xys"/>
|
||||
<constraint firstItem="XX4-n6-hCm" firstAttribute="width" secondItem="iN0-l3-epB" secondAttribute="width" id="WhE-lH-ZtR"/>
|
||||
<constraint firstItem="BGD-sd-SQR" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="X14-4s-uGM"/>
|
||||
<constraint firstAttribute="trailing" secondItem="nLd-BP-JAE" secondAttribute="trailing" id="YAu-gd-ItG"/>
|
||||
<constraint firstItem="XX4-n6-hCm" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="csl-KT-4s9"/>
|
||||
<constraint firstItem="BGD-sd-SQR" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="haP-Kv-OLI"/>
|
||||
<constraint firstAttribute="bottom" secondItem="nLd-BP-JAE" secondAttribute="bottom" id="kQ6-Cg-FMi"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -134,7 +134,7 @@ final class RoomCoordinator: NSObject, RoomCoordinatorProtocol {
|
||||
self.selectedEventId = eventId
|
||||
|
||||
if self.hasStartedOnce {
|
||||
self.roomViewController.highlightEvent(eventId, completion: completion)
|
||||
self.roomViewController.highlightAndDisplayEvent(eventId, completion: completion)
|
||||
} else {
|
||||
self.start(withCompletion: completion)
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ extern NSNotificationName const RoomGroupCallTileTappedNotification;
|
||||
@param eventId Identifier of the event to be highlighted.
|
||||
@param completion Completion block to be called at the end of process. Optional.
|
||||
*/
|
||||
- (void)highlightEvent:(NSString *)eventId completion:(nullable void (^)(void))completion;
|
||||
- (void)highlightAndDisplayEvent:(NSString *)eventId completion:(nullable void (^)(void))completion;
|
||||
|
||||
/**
|
||||
Creates and returns a new `RoomViewController` object.
|
||||
|
||||
@@ -54,55 +54,7 @@
|
||||
#import "JitsiViewController.h"
|
||||
|
||||
#import "RoomEmptyBubbleCell.h"
|
||||
|
||||
#import "RoomIncomingTextMsgBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomIncomingEncryptedTextMsgBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomOutgoingTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomOutgoingEncryptedTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomMembershipBubbleCell.h"
|
||||
#import "RoomMembershipWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomMembershipCollapsedBubbleCell.h"
|
||||
#import "RoomMembershipCollapsedWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomMembershipExpandedBubbleCell.h"
|
||||
#import "RoomMembershipExpandedWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomCreationWithPaginationCollapsedBubbleCell.h"
|
||||
#import "RoomCreationCollapsedBubbleCell.h"
|
||||
|
||||
#import "RoomSelectedStickerBubbleCell.h"
|
||||
#import "RoomPredecessorBubbleCell.h"
|
||||
|
||||
#import "MXKRoomBubbleTableViewCell+Riot.h"
|
||||
|
||||
#import "AvatarGenerator.h"
|
||||
@@ -130,6 +82,8 @@
|
||||
|
||||
#import "MXSDKOptions.h"
|
||||
|
||||
#import "RoomTimelineCellProvider.h"
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNotification";
|
||||
@@ -139,7 +93,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
@interface RoomViewController () <UISearchBarDelegate, UIGestureRecognizerDelegate, UIScrollViewAccessibilityDelegate, RoomTitleViewTapGestureDelegate, RoomParticipantsViewControllerDelegate, MXKRoomMemberDetailsViewControllerDelegate, ContactsTableViewControllerDelegate, MXServerNoticesDelegate, RoomContextualMenuViewControllerDelegate,
|
||||
ReactionsMenuViewModelCoordinatorDelegate, EditHistoryCoordinatorBridgePresenterDelegate, MXKDocumentPickerPresenterDelegate, EmojiPickerCoordinatorBridgePresenterDelegate,
|
||||
ReactionHistoryCoordinatorBridgePresenterDelegate, CameraPresenterDelegate, MediaPickerCoordinatorBridgePresenterDelegate,
|
||||
RoomDataSourceDelegate, RoomCreationModalCoordinatorBridgePresenterDelegate, RoomInfoCoordinatorBridgePresenterDelegate, DialpadViewControllerDelegate, RemoveJitsiWidgetViewDelegate, VoiceMessageControllerDelegate, SpaceDetailPresenterDelegate, UserSuggestionCoordinatorBridgeDelegate, RoomCoordinatorBridgePresenterDelegate, ThreadsCoordinatorBridgePresenterDelegate, MXThreadingServiceDelegate>
|
||||
RoomDataSourceDelegate, RoomCreationModalCoordinatorBridgePresenterDelegate, RoomInfoCoordinatorBridgePresenterDelegate, DialpadViewControllerDelegate, RemoveJitsiWidgetViewDelegate, VoiceMessageControllerDelegate, SpaceDetailPresenterDelegate, UserSuggestionCoordinatorBridgeDelegate, ThreadsCoordinatorBridgePresenterDelegate, MXThreadingServiceDelegate>
|
||||
{
|
||||
|
||||
// The preview header
|
||||
@@ -246,9 +200,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
@property (nonatomic, strong) RoomMessageURLParser *roomMessageURLParser;
|
||||
@property (nonatomic, strong) RoomCreationModalCoordinatorBridgePresenter *roomCreationModalCoordinatorBridgePresenter;
|
||||
@property (nonatomic, strong) RoomInfoCoordinatorBridgePresenter *roomInfoCoordinatorBridgePresenter;
|
||||
@property (nonatomic, strong) RoomCoordinatorBridgePresenter *threadBridgePresenter;
|
||||
@property (nonatomic, strong) CustomSizedPresentationController *customSizedPresentationController;
|
||||
@property (nonatomic, strong) ThreadsCoordinatorBridgePresenter *threadsCoordinatorBridgePresenter;
|
||||
@property (nonatomic, strong) ThreadsCoordinatorBridgePresenter *threadsBridgePresenter;
|
||||
@property (nonatomic, getter=isActivitiesViewExpanded) BOOL activitiesViewExpanded;
|
||||
@property (nonatomic, getter=isScrollToBottomHidden) BOOL scrollToBottomHidden;
|
||||
@property (nonatomic, getter=isMissedDiscussionsBadgeHidden) BOOL missedDiscussionsBadgeHidden;
|
||||
@@ -372,83 +325,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
[super viewDidLoad];
|
||||
|
||||
// Register first customized cell view classes used to render bubbles
|
||||
[self.bubblesTableView registerClass:RoomIncomingTextMsgBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingAttachmentBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedTextMsgBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedAttachmentBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomOutgoingAttachmentBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingTextMsgBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedAttachmentBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedTextMsgBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomEmptyBubbleCell.class forCellReuseIdentifier:RoomEmptyBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomMembershipBubbleCell.class forCellReuseIdentifier:RoomMembershipBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomMembershipWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomMembershipCollapsedBubbleCell.class forCellReuseIdentifier:RoomMembershipCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomMembershipCollapsedWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipCollapsedWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomMembershipExpandedBubbleCell.class forCellReuseIdentifier:RoomMembershipExpandedBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomMembershipExpandedWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipExpandedWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomSelectedStickerBubbleCell.class forCellReuseIdentifier:RoomSelectedStickerBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomPredecessorBubbleCell.class forCellReuseIdentifier:RoomPredecessorBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:KeyVerificationIncomingRequestApprovalBubbleCell.class forCellReuseIdentifier:KeyVerificationIncomingRequestApprovalBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:KeyVerificationRequestStatusBubbleCell.class forCellReuseIdentifier:KeyVerificationRequestStatusBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:KeyVerificationRequestStatusWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationRequestStatusWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:KeyVerificationConclusionBubbleCell.class forCellReuseIdentifier:KeyVerificationConclusionBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:KeyVerificationConclusionWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationConclusionWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomCreationCollapsedBubbleCell.class forCellReuseIdentifier:RoomCreationCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomCreationWithPaginationCollapsedBubbleCell.class forCellReuseIdentifier:RoomCreationWithPaginationCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
// call cells
|
||||
[self.bubblesTableView registerClass:RoomDirectCallStatusBubbleCell.class forCellReuseIdentifier:RoomDirectCallStatusBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:RoomGroupCallStatusBubbleCell.class forCellReuseIdentifier:RoomGroupCallStatusBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:RoomCreationIntroCell.class forCellReuseIdentifier:RoomCreationIntroCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerNib:RoomTypingBubbleCell.nib forCellReuseIdentifier:RoomTypingBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[self.bubblesTableView registerClass:VoiceMessageBubbleCell.class forCellReuseIdentifier:VoiceMessageBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:VoiceMessageWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:VoiceMessageWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[self.bubblesTableView registerClass:VoiceMessageWithPaginationTitleBubbleCell.class forCellReuseIdentifier:VoiceMessageWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[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];
|
||||
[[RoomTimelineConfiguration shared].currentStyle.cellProvider registerCellsForTableView:self.bubblesTableView];
|
||||
|
||||
[self vc_removeBackTitle];
|
||||
|
||||
@@ -2271,6 +2148,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
[MXSDKOptions sharedInstance].videoConversionPresetName = presetName;
|
||||
[roomInputToolbarView sendSelectedVideoAsset:videoAsset isPhotoLibraryAsset:isPhotoLibraryAsset];
|
||||
}];
|
||||
compressionPrompt.popoverPresentationController.sourceView = roomInputToolbarView.attachMediaButton;
|
||||
compressionPrompt.popoverPresentationController.sourceRect = roomInputToolbarView.attachMediaButton.bounds;
|
||||
|
||||
[self presentViewController:compressionPrompt animated:YES completion:nil];
|
||||
}
|
||||
@@ -2733,14 +2612,23 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
|
||||
- (Class<MXKCellRendering>)cellViewClassForCellData:(MXKCellData*)cellData
|
||||
{
|
||||
Class cellViewClass = nil;
|
||||
BOOL showEncryptionBadge = NO;
|
||||
RoomTimelineCellIdentifier cellIdentifier = [self cellIdentifierForCellData:cellData andRoomDataSource:customizedRoomDataSource];
|
||||
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
return [timelineConfiguration.currentStyle.cellProvider cellViewClassForCellIdentifier:cellIdentifier];;
|
||||
}
|
||||
|
||||
- (RoomTimelineCellIdentifier)cellIdentifierForCellData:(MXKCellData*)cellData andRoomDataSource:(RoomDataSource *)customizedRoomDataSource;
|
||||
{
|
||||
// Sanity check
|
||||
if (![cellData conformsToProtocol:@protocol(MXKRoomBubbleCellDataStoring)])
|
||||
{
|
||||
return nil;
|
||||
return RoomTimelineCellIdentifierUnknown;
|
||||
}
|
||||
|
||||
BOOL showEncryptionBadge = NO;
|
||||
RoomTimelineCellIdentifier cellIdentifier;
|
||||
|
||||
id<MXKRoomBubbleCellDataStoring> bubbleData = (id<MXKRoomBubbleCellDataStoring>)cellData;
|
||||
|
||||
@@ -2755,27 +2643,27 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
// Select the suitable table view cell class, by considering first the empty bubble cell.
|
||||
if (bubbleData.hasNoDisplay)
|
||||
{
|
||||
cellViewClass = RoomEmptyBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierEmpty;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagRoomCreationIntro)
|
||||
{
|
||||
cellViewClass = RoomCreationIntroCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierRoomCreationIntro;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagRoomCreateWithPredecessor)
|
||||
{
|
||||
cellViewClass = RoomPredecessorBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierRoomPredecessor;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagKeyVerificationRequestIncomingApproval)
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.class : KeyVerificationIncomingRequestApprovalBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierKeyVerificationIncomingRequestApprovalWithPaginationTitle : RoomTimelineCellIdentifierKeyVerificationIncomingRequestApproval;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagKeyVerificationRequest)
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? KeyVerificationRequestStatusWithPaginationTitleBubbleCell.class : KeyVerificationRequestStatusBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierKeyVerificationRequestStatusWithPaginationTitle : RoomTimelineCellIdentifierKeyVerificationRequestStatus;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagKeyVerificationConclusion)
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? KeyVerificationConclusionWithPaginationTitleBubbleCell.class : KeyVerificationConclusionBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierKeyVerificationConclusionWithPaginationTitle : RoomTimelineCellIdentifierKeyVerificationConclusion;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagMembership)
|
||||
{
|
||||
@@ -2783,80 +2671,80 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
{
|
||||
if (bubbleData.nextCollapsableCellData)
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? RoomMembershipCollapsedWithPaginationTitleBubbleCell.class : RoomMembershipCollapsedBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierMembershipCollapsedWithPaginationTitle : RoomTimelineCellIdentifierMembershipCollapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use a normal membership cell for a single membership event
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? RoomMembershipWithPaginationTitleBubbleCell.class : RoomMembershipBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierMembershipWithPaginationTitle : RoomTimelineCellIdentifierMembership;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.collapsedAttributedTextMessage)
|
||||
{
|
||||
// The cell (and its series) is not collapsed but this cell is the first
|
||||
// of the series. So, use the cell with the "collapse" button.
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? RoomMembershipExpandedWithPaginationTitleBubbleCell.class : RoomMembershipExpandedBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierMembershipExpandedWithPaginationTitle : RoomTimelineCellIdentifierMembershipExpanded;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? RoomMembershipWithPaginationTitleBubbleCell.class : RoomMembershipBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierMembershipWithPaginationTitle : RoomTimelineCellIdentifierMembership;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagRoomCreateConfiguration)
|
||||
{
|
||||
cellViewClass = bubbleData.isPaginationFirstBubble ? RoomCreationWithPaginationCollapsedBubbleCell.class : RoomCreationCollapsedBubbleCell.class;
|
||||
cellIdentifier = bubbleData.isPaginationFirstBubble ? RoomTimelineCellIdentifierRoomCreationCollapsedWithPaginationTitle : RoomTimelineCellIdentifierRoomCreationCollapsed;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagCall)
|
||||
{
|
||||
cellViewClass = RoomDirectCallStatusBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierDirectCallStatus;
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagGroupCall)
|
||||
{
|
||||
cellViewClass = RoomGroupCallStatusBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierGroupCallStatus;
|
||||
}
|
||||
else if (bubbleData.attachment.type == MXKAttachmentTypeVoiceMessage || bubbleData.attachment.type == MXKAttachmentTypeAudio)
|
||||
{
|
||||
if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellViewClass = VoiceMessageWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierVoiceMessageWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = VoiceMessageWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierVoiceMessageWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = VoiceMessageBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierVoiceMessage;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagPoll)
|
||||
{
|
||||
if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellViewClass = PollWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierPollWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = PollWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierPollWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = PollBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierPoll;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagLocation)
|
||||
{
|
||||
if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellViewClass = LocationWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierLocationWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = LocationWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierLocationWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = LocationBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierLocation;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.isIncoming)
|
||||
@@ -2866,19 +2754,19 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
// Check whether the provided celldata corresponds to a selected sticker
|
||||
if (customizedRoomDataSource.selectedEventId && (bubbleData.attachment.type == MXKAttachmentTypeSticker) && [bubbleData.attachment.eventId isEqualToString:customizedRoomDataSource.selectedEventId])
|
||||
{
|
||||
cellViewClass = RoomSelectedStickerBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierSelectedSticker;
|
||||
}
|
||||
else if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.class : RoomIncomingAttachmentWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithPaginationTitle : RoomTimelineCellIdentifierIncomingAttachmentWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.class : RoomIncomingAttachmentWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithoutSenderInfo : RoomTimelineCellIdentifierIncomingAttachmentWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedAttachmentBubbleCell.class : RoomIncomingAttachmentBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingAttachmentEncrypted : RoomTimelineCellIdentifierIncomingAttachment;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2887,24 +2775,24 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
{
|
||||
if (bubbleData.shouldHideSenderName)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class : RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitleWithoutSenderName : RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitleWithoutSenderName;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.class : RoomIncomingTextMsgWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitle : RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitle;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.class : RoomIncomingTextMsgWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderInfo : RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderInfo;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderName)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.class : RoomIncomingTextMsgWithoutSenderNameBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderName : RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderName;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomIncomingEncryptedTextMsgBubbleCell.class : RoomIncomingTextMsgBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierIncomingTextMessageEncrypted : RoomTimelineCellIdentifierIncomingTextMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2916,19 +2804,19 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
// Check whether the provided celldata corresponds to a selected sticker
|
||||
if (customizedRoomDataSource.selectedEventId && (bubbleData.attachment.type == MXKAttachmentTypeSticker) && [bubbleData.attachment.eventId isEqualToString:customizedRoomDataSource.selectedEventId])
|
||||
{
|
||||
cellViewClass = RoomSelectedStickerBubbleCell.class;
|
||||
cellIdentifier = RoomTimelineCellIdentifierSelectedSticker;
|
||||
}
|
||||
else if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.class :RoomOutgoingAttachmentWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithPaginationTitle : RoomTimelineCellIdentifierOutgoingAttachmentWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class : RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithoutSenderInfo : RoomTimelineCellIdentifierOutgoingAttachmentWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedAttachmentBubbleCell.class : RoomOutgoingAttachmentBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingAttachmentEncrypted : RoomTimelineCellIdentifierOutgoingAttachment;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2937,29 +2825,29 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
{
|
||||
if (bubbleData.shouldHideSenderName)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class : RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitleWithoutSenderName : RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitleWithoutSenderName;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.class : RoomOutgoingTextMsgWithPaginationTitleBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitle : RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitle;
|
||||
}
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class :RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderInfo : RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderInfo;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderName)
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.class : RoomOutgoingTextMsgWithoutSenderNameBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderName : RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderName;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellViewClass = showEncryptionBadge ? RoomOutgoingEncryptedTextMsgBubbleCell.class : RoomOutgoingTextMsgBubbleCell.class;
|
||||
cellIdentifier = showEncryptionBadge ? RoomTimelineCellIdentifierOutgoingTextMessageEncrypted : RoomTimelineCellIdentifierOutgoingTextMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cellViewClass;
|
||||
return cellIdentifier;
|
||||
}
|
||||
|
||||
#pragma mark - MXKDataSource delegate
|
||||
@@ -3426,6 +3314,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
[self cancelEventSelection];
|
||||
|
||||
[self presentEventForwardingDialogForSelectedEvent:selectedEvent];
|
||||
}]];
|
||||
}
|
||||
@@ -3455,6 +3346,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
[self cancelEventSelection];
|
||||
|
||||
[self presentEventForwardingDialogForSelectedEvent:selectedEvent];
|
||||
}]];
|
||||
}
|
||||
@@ -3496,6 +3390,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
[self cancelEventSelection];
|
||||
|
||||
[self presentEventForwardingDialogForSelectedEvent:selectedEvent];
|
||||
}]];
|
||||
}
|
||||
@@ -3657,10 +3554,11 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
|
||||
// Create a matrix.to permalink that is common to all matrix clients
|
||||
NSString *permalink = [MXTools permalinkToEvent:selectedEvent.eventId inRoom:selectedEvent.roomId];
|
||||
NSURL *url = [NSURL URLWithString:permalink];
|
||||
|
||||
if (permalink)
|
||||
if (url)
|
||||
{
|
||||
MXKPasteboardManager.shared.pasteboard.string = permalink;
|
||||
MXKPasteboardManager.shared.pasteboard.URL = url;
|
||||
[self.view vc_toastWithMessage:VectorL10n.roomEventCopyLinkInfo
|
||||
image:[UIImage imageNamed:@"link_icon"]
|
||||
duration:2.0
|
||||
@@ -3711,24 +3609,21 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
if (selectedEvent.eventType != MXEventTypeRoomEncryption)
|
||||
{
|
||||
NSString *title;
|
||||
UIAlertActionStyle style;
|
||||
EventMenuItemType itemType;
|
||||
if (selectedEvent.eventType == MXEventTypePollStart)
|
||||
{
|
||||
title = [VectorL10n roomEventActionRemovePoll];
|
||||
style = UIAlertActionStyleDefault;
|
||||
itemType = EventMenuItemTypeRemovePoll;
|
||||
}
|
||||
else
|
||||
{
|
||||
title = [VectorL10n roomEventActionRedact];
|
||||
style = UIAlertActionStyleDestructive;
|
||||
itemType = EventMenuItemTypeRemove;
|
||||
}
|
||||
|
||||
[self.eventMenuBuilder addItemWithType:itemType
|
||||
action:[UIAlertAction actionWithTitle:title
|
||||
style:style
|
||||
style:UIAlertActionStyleDestructive
|
||||
handler:^(UIAlertAction * action) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
@@ -4545,10 +4440,11 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
|
||||
- (IBAction)onThreadListTapped:(id)sender
|
||||
{
|
||||
self.threadsCoordinatorBridgePresenter = [[ThreadsCoordinatorBridgePresenter alloc] initWithSession:self.mainSession
|
||||
roomId:self.roomDataSource.roomId];
|
||||
self.threadsCoordinatorBridgePresenter.delegate = self;
|
||||
[self.threadsCoordinatorBridgePresenter pushFrom:self.navigationController animated:YES];
|
||||
self.threadsBridgePresenter = [[ThreadsCoordinatorBridgePresenter alloc] initWithSession:self.mainSession
|
||||
roomId:self.roomDataSource.roomId
|
||||
threadId:nil];
|
||||
self.threadsBridgePresenter.delegate = self;
|
||||
[self.threadsBridgePresenter pushFrom:self.navigationController animated:YES];
|
||||
}
|
||||
|
||||
- (IBAction)onIntegrationsPressed:(id)sender
|
||||
@@ -6571,25 +6467,20 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
|
||||
- (void)openThreadWithId:(NSString *)threadId
|
||||
{
|
||||
if (self.threadBridgePresenter)
|
||||
if (self.threadsBridgePresenter)
|
||||
{
|
||||
[self.threadBridgePresenter dismissWithAnimated:YES completion:nil];
|
||||
self.threadBridgePresenter = nil;
|
||||
[self.threadsBridgePresenter dismissWithAnimated:YES completion:nil];
|
||||
self.threadsBridgePresenter = nil;
|
||||
}
|
||||
|
||||
RoomDisplayConfiguration *configuration = RoomDisplayConfiguration.forThreads;
|
||||
RoomCoordinatorBridgePresenterParameters *parameters = [[RoomCoordinatorBridgePresenterParameters alloc] initWithSession:self.mainSession
|
||||
roomId:self.roomDataSource.roomId
|
||||
eventId:nil
|
||||
threadId:threadId
|
||||
displayConfiguration:configuration
|
||||
previewData:nil];
|
||||
self.threadBridgePresenter = [[RoomCoordinatorBridgePresenter alloc] initWithParameters:parameters];
|
||||
self.threadBridgePresenter.delegate = self;
|
||||
[self.threadBridgePresenter pushFrom:self.navigationController animated:YES];
|
||||
|
||||
self.threadsBridgePresenter = [[ThreadsCoordinatorBridgePresenter alloc] initWithSession:self.mainSession
|
||||
roomId:self.roomDataSource.roomId
|
||||
threadId:threadId];
|
||||
self.threadsBridgePresenter.delegate = self;
|
||||
[self.threadsBridgePresenter pushFrom:self.navigationController animated:YES];
|
||||
}
|
||||
|
||||
- (void)highlightEvent:(NSString *)eventId completion:(void (^)(void))completion
|
||||
- (void)highlightAndDisplayEvent:(NSString *)eventId completion:(void (^)(void))completion
|
||||
{
|
||||
NSInteger row = [self.roomDataSource indexOfCellDataWithEventId:eventId];
|
||||
if (row == NSNotFound)
|
||||
@@ -7100,66 +6991,29 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
|
||||
[self mention:member];
|
||||
}
|
||||
|
||||
#pragma mark - RoomCoordinatorBridgePresenterDelegate
|
||||
|
||||
- (void)roomCoordinatorBridgePresenterDidLeaveRoom:(RoomCoordinatorBridgePresenter *)bridgePresenter
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)roomCoordinatorBridgePresenterDidCancelRoomPreview:(RoomCoordinatorBridgePresenter *)bridgePresenter
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)roomCoordinatorBridgePresenter:(RoomCoordinatorBridgePresenter *)bridgePresenter
|
||||
didSelectRoomWithId:(NSString *)roomId
|
||||
eventId:(NSString*)eventId
|
||||
{
|
||||
if (bridgePresenter == self.threadBridgePresenter && [roomId isEqualToString:self.roomDataSource.roomId] && eventId)
|
||||
{
|
||||
// thread view wants to highlight an event in the timeline
|
||||
// dismiss thread view first
|
||||
MXWeakify(self);
|
||||
[self.threadBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
[self highlightEvent:eventId completion:nil];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)roomCoordinatorBridgePresenterDidDismissInteractively:(RoomCoordinatorBridgePresenter *)bridgePresenter
|
||||
{
|
||||
if (bridgePresenter == self.threadBridgePresenter)
|
||||
{
|
||||
self.threadBridgePresenter = nil;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - ThreadsCoordinatorBridgePresenterDelegate
|
||||
|
||||
- (void)threadsCoordinatorBridgePresenterDelegateDidComplete:(ThreadsCoordinatorBridgePresenter *)coordinatorBridgePresenter
|
||||
{
|
||||
self.threadsCoordinatorBridgePresenter = nil;
|
||||
self.threadsBridgePresenter = nil;
|
||||
}
|
||||
|
||||
- (void)threadsCoordinatorBridgePresenterDelegateDidSelect:(ThreadsCoordinatorBridgePresenter *)coordinatorBridgePresenter roomId:(NSString *)roomId eventId:(NSString *)eventId
|
||||
{
|
||||
MXWeakify(self);
|
||||
[self.threadsCoordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
[self.threadsBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
if (eventId)
|
||||
{
|
||||
[self highlightEvent:eventId completion:nil];
|
||||
[self highlightAndDisplayEvent:eventId completion:nil];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)threadsCoordinatorBridgePresenterDidDismissInteractively:(ThreadsCoordinatorBridgePresenter *)coordinatorBridgePresenter
|
||||
{
|
||||
self.threadsCoordinatorBridgePresenter = nil;
|
||||
self.threadsBridgePresenter = nil;
|
||||
}
|
||||
|
||||
#pragma mark - MXThreadingServiceDelegate
|
||||
|
||||
@@ -127,57 +127,62 @@
|
||||
// Display date for each message
|
||||
[bubbleCell addDateLabel];
|
||||
|
||||
RoomBubbleCellData *cellData = (RoomBubbleCellData*)[self cellDataAtIndex:indexPath.row];
|
||||
MXEvent *event = cellData.events.firstObject;
|
||||
|
||||
if (event)
|
||||
if (RiotSettings.shared.enableThreads)
|
||||
{
|
||||
if (cellData.hasThreadRoot)
|
||||
RoomBubbleCellData *cellData = (RoomBubbleCellData*)[self cellDataAtIndex:indexPath.row];
|
||||
MXEvent *event = cellData.events.firstObject;
|
||||
|
||||
if (event)
|
||||
{
|
||||
MXThread *thread = cellData.bubbleComponents.firstObject.thread;
|
||||
ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread];
|
||||
[bubbleCell.tmpSubviews addObject:threadSummaryView];
|
||||
if (cellData.hasThreadRoot)
|
||||
{
|
||||
MXThread *thread = cellData.bubbleComponents.firstObject.thread;
|
||||
ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread];
|
||||
[bubbleCell.tmpSubviews addObject:threadSummaryView];
|
||||
|
||||
threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[bubbleCell.contentView addSubview:threadSummaryView];
|
||||
threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[bubbleCell.contentView addSubview:threadSummaryView];
|
||||
|
||||
CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin;
|
||||
CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin;
|
||||
CGFloat height = [ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth];
|
||||
|
||||
CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0];
|
||||
CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height;
|
||||
CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0];
|
||||
CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height;
|
||||
|
||||
// Set constraints for the summary view
|
||||
[NSLayoutConstraint activateConstraints: @[
|
||||
[threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor
|
||||
constant:leftMargin],
|
||||
[threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor
|
||||
// Set constraints for the summary view
|
||||
[NSLayoutConstraint activateConstraints: @[
|
||||
[threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor
|
||||
constant:leftMargin],
|
||||
[threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor
|
||||
constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin],
|
||||
[threadSummaryView.heightAnchor constraintEqualToConstant:[ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth]],
|
||||
[threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin]
|
||||
]];
|
||||
}
|
||||
else if (event.isInThread)
|
||||
{
|
||||
FromThreadView *fromThreadView = [FromThreadView instantiate];
|
||||
[bubbleCell.tmpSubviews addObject:fromThreadView];
|
||||
[threadSummaryView.heightAnchor constraintEqualToConstant:height],
|
||||
[threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin]
|
||||
]];
|
||||
}
|
||||
else if (event.isInThread)
|
||||
{
|
||||
FromAThreadView *fromAThreadView = [FromAThreadView instantiate];
|
||||
[bubbleCell.tmpSubviews addObject:fromAThreadView];
|
||||
|
||||
fromAThreadView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[bubbleCell.contentView addSubview:fromAThreadView];
|
||||
|
||||
fromThreadView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[bubbleCell.contentView addSubview:fromThreadView];
|
||||
CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin;
|
||||
CGFloat height = [FromAThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth];
|
||||
|
||||
CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin;
|
||||
CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0];
|
||||
CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height;
|
||||
|
||||
CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0];
|
||||
CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height;
|
||||
|
||||
// Set constraints for the summary view
|
||||
[NSLayoutConstraint activateConstraints: @[
|
||||
[fromThreadView.leadingAnchor constraintEqualToAnchor:fromThreadView.superview.leadingAnchor
|
||||
constant:leftMargin],
|
||||
[fromThreadView.topAnchor constraintEqualToAnchor:fromThreadView.superview.topAnchor
|
||||
constant:bottomPositionY + RoomBubbleCellLayout.fromThreadViewTopMargin],
|
||||
[fromThreadView.heightAnchor constraintEqualToConstant:[FromThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth]],
|
||||
[fromThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromThreadView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin]
|
||||
]];
|
||||
// Set constraints for the summary view
|
||||
[NSLayoutConstraint activateConstraints: @[
|
||||
[fromAThreadView.leadingAnchor constraintEqualToAnchor:fromAThreadView.superview.leadingAnchor
|
||||
constant:leftMargin],
|
||||
[fromAThreadView.topAnchor constraintEqualToAnchor:fromAThreadView.superview.topAnchor
|
||||
constant:bottomPositionY + RoomBubbleCellLayout.fromAThreadViewTopMargin],
|
||||
[fromAThreadView.heightAnchor constraintEqualToConstant:height],
|
||||
[fromAThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromAThreadView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin]
|
||||
]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1041,10 +1041,11 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti
|
||||
// Create a matrix.to permalink to the room
|
||||
|
||||
NSString *permalink = [MXTools permalinkToRoom:roomAliasLabel.text];
|
||||
|
||||
if (permalink)
|
||||
NSURL *url = [NSURL URLWithString:permalink];
|
||||
|
||||
if (url)
|
||||
{
|
||||
MXKPasteboardManager.shared.pasteboard.string = permalink;
|
||||
MXKPasteboardManager.shared.pasteboard.URL = url;
|
||||
[self.view vc_toastWithMessage:VectorL10n.roomEventCopyLinkInfo
|
||||
image:[UIImage imageNamed:@"link_icon"]
|
||||
duration:2.0
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
Copyright 2018 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 "MXKTableViewCell.h"
|
||||
#import "MXKCellRendering.h"
|
||||
#import "MXKReceiptSendersContainer.h"
|
||||
|
||||
#import <WebKit/WebKit.h>
|
||||
|
||||
@class MXKImageView;
|
||||
@class MXKPieChartView;
|
||||
@class MXKRoomBubbleCellData;
|
||||
|
||||
#pragma mark - MXKCellRenderingDelegate cell tap locations
|
||||
|
||||
/**
|
||||
Action identifier used when the user tapped on message text view.
|
||||
|
||||
The `userInfo` dictionary contains an `MXEvent` object under the `kMXKRoomBubbleCellEventKey` key, representing the tapped event.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellTapOnMessageTextView;
|
||||
|
||||
/**
|
||||
Action identifier used when the user tapped on user name label.
|
||||
|
||||
The `userInfo` dictionary contains an `NSString` object under the `kMXKRoomBubbleCellUserIdKey` key, representing the user id of the tapped name label.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellTapOnSenderNameLabel;
|
||||
|
||||
/**
|
||||
Action identifier used when the user tapped on avatar view.
|
||||
|
||||
The `userInfo` dictionary contains an `NSString` object under the `kMXKRoomBubbleCellUserIdKey` key, representing the user id of the tapped avatar.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellTapOnAvatarView;
|
||||
|
||||
/**
|
||||
Action identifier used when the user tapped on date/time container.
|
||||
|
||||
The `userInfo` is nil.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellTapOnDateTimeContainer;
|
||||
|
||||
/**
|
||||
Action identifier used when the user tapped on attachment view.
|
||||
|
||||
The `userInfo` is nil. The attachment can be retrieved via MXKRoomBubbleTableViewCell.attachmentView.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellTapOnAttachmentView;
|
||||
|
||||
/**
|
||||
Action identifier used when the user tapped on overlay container.
|
||||
|
||||
The `userInfo` is nil
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellTapOnOverlayContainer;
|
||||
|
||||
/**
|
||||
Action identifier used when the user tapped on content view.
|
||||
|
||||
The `userInfo` dictionary may contain an `MXEvent` object under the `kMXKRoomBubbleCellEventKey` key, representing the event displayed at the level of the tapped line. This dictionary is empty if no event correspond to the tapped position.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellTapOnContentView;
|
||||
|
||||
/**
|
||||
Action identifier used when the user pressed unsent button displayed in front of an unsent event.
|
||||
|
||||
The `userInfo` dictionary contains an `MXEvent` object under the `kMXKRoomBubbleCellEventKey` key, representing the unsent event.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellUnsentButtonPressed;
|
||||
|
||||
/**
|
||||
Action identifier used when the user long pressed on a displayed event.
|
||||
|
||||
The `userInfo` dictionary contains an `MXEvent` object under the `kMXKRoomBubbleCellEventKey` key, representing the selected event.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellLongPressOnEvent;
|
||||
|
||||
/**
|
||||
Action identifier used when the user long pressed on progress view.
|
||||
|
||||
The `userInfo` is nil. The progress view can be retrieved via MXKRoomBubbleTableViewCell.progressView.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellLongPressOnProgressView;
|
||||
|
||||
/**
|
||||
Action identifier used when the user long pressed on avatar view.
|
||||
|
||||
The `userInfo` dictionary contains an `NSString` object under the `kMXKRoomBubbleCellUserIdKey` key, representing the user id of the concerned avatar.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellLongPressOnAvatarView;
|
||||
|
||||
/**
|
||||
Action identifier used when the user clicked on a link.
|
||||
|
||||
This action is sent via the MXKCellRenderingDelegate `shouldDoAction` operation.
|
||||
|
||||
The `userInfo` dictionary contains a `NSURL` object under the `kMXKRoomBubbleCellUrl` key, representing the url the user wants to open. And a NSNumber wrapping `UITextItemInteraction` raw value, representing the type of interaction expected with the URL, under the `kMXKRoomBubbleCellUrlItemInteraction` key.
|
||||
|
||||
The shouldDoAction implementation must return NO to prevent the system (safari) from opening the link.
|
||||
|
||||
@discussion: If the link refers to a room alias/id, a user id or an event id, the non-ASCII characters (like '#' in room alias) has been
|
||||
escaped to be able to convert it into a legal URL string.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellShouldInteractWithURL;
|
||||
|
||||
/**
|
||||
Notifications `userInfo` keys
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellUserIdKey;
|
||||
extern NSString *const kMXKRoomBubbleCellEventKey;
|
||||
extern NSString *const kMXKRoomBubbleCellEventIdKey;
|
||||
extern NSString *const kMXKRoomBubbleCellReceiptsContainerKey;
|
||||
extern NSString *const kMXKRoomBubbleCellUrl;
|
||||
extern NSString *const kMXKRoomBubbleCellUrlItemInteraction;
|
||||
|
||||
#pragma mark - MXKRoomBubbleTableViewCell
|
||||
|
||||
/**
|
||||
`MXKRoomBubbleTableViewCell` is a base class for displaying a room bubble.
|
||||
|
||||
This class is used to handle a maximum of items which may be present in bubbles display (like the user's picture view, the message text view...).
|
||||
To optimize bubbles rendering, we advise to define a .xib for each kind of bubble layout (with or without sender's information, with or without attachment...).
|
||||
Each inherited class should define only the actual displayed items.
|
||||
*/
|
||||
@interface MXKRoomBubbleTableViewCell : MXKTableViewCell <MXKCellRendering, UITextViewDelegate, WKNavigationDelegate>
|
||||
{
|
||||
@protected
|
||||
/**
|
||||
The current bubble data displayed by the table view cell
|
||||
*/
|
||||
MXKRoomBubbleCellData *bubbleData;
|
||||
}
|
||||
|
||||
/**
|
||||
The current bubble data displayed by the table view cell
|
||||
*/
|
||||
@property (strong, nonatomic, readonly) MXKRoomBubbleCellData *bubbleData;
|
||||
|
||||
/**
|
||||
Option to highlight or not the content of message text view (May be used in case of text selection).
|
||||
NO by default.
|
||||
*/
|
||||
@property (nonatomic) BOOL allTextHighlighted;
|
||||
|
||||
/**
|
||||
Tell whether the animation should start automatically in case of animated gif (NO by default).
|
||||
*/
|
||||
@property (nonatomic) BOOL isAutoAnimatedGif;
|
||||
|
||||
/**
|
||||
The default picture displayed when no picture is available.
|
||||
*/
|
||||
@property (nonatomic) UIImage *picturePlaceholder;
|
||||
|
||||
/**
|
||||
The list of the temporary subviews that should be removed before reusing the cell (empty array by default).
|
||||
*/
|
||||
@property (nonatomic) NSMutableArray<UIView*> *tmpSubviews;
|
||||
|
||||
/**
|
||||
The read receipts alignment.
|
||||
By default, they are left aligned.
|
||||
*/
|
||||
@property (nonatomic) ReadReceiptsAlignment readReceiptsAlignment;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UILabel *userNameLabel;
|
||||
@property (weak, nonatomic) IBOutlet UIView *userNameTapGestureMaskView;
|
||||
@property (strong, nonatomic) IBOutlet MXKImageView *pictureView;
|
||||
@property (weak, nonatomic) IBOutlet UITextView *messageTextView;
|
||||
@property (strong, nonatomic) IBOutlet MXKImageView *attachmentView;
|
||||
@property (strong, nonatomic) IBOutlet UIImageView *playIconView;
|
||||
@property (strong, nonatomic) IBOutlet UIImageView *fileTypeIconView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *bubbleInfoContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *bubbleOverlayContainer;
|
||||
|
||||
/**
|
||||
The container view in which the encryption information may be displayed
|
||||
*/
|
||||
@property (weak, nonatomic) IBOutlet UIView *encryptionStatusContainerView;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIView *progressView;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *statsLabel;
|
||||
@property (weak, nonatomic) IBOutlet MXKPieChartView *progressChartView;
|
||||
|
||||
/**
|
||||
The constraints which defines the relationship between messageTextView and its superview.
|
||||
The defined constant are supposed >= 0.
|
||||
*/
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *msgTextViewTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *msgTextViewBottomConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *msgTextViewLeadingConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *msgTextViewTrailingConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *msgTextViewWidthConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *msgTextViewMinHeightConstraint;
|
||||
|
||||
/**
|
||||
The constraints which defines the relationship between attachmentView and its superview
|
||||
The defined constant are supposed >= 0.
|
||||
*/
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewWidthConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewMinHeightConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewBottomConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewLeadingConstraint;
|
||||
|
||||
/**
|
||||
The constraints which defines the relationship between bubbleInfoContainer and its superview
|
||||
The defined constant are supposed >= 0.
|
||||
*/
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bubbleInfoContainerTopConstraint;
|
||||
|
||||
/**
|
||||
The read marker view and its layout constraints (nil by default).
|
||||
*/
|
||||
@property (nonatomic) UIView *readMarkerView;
|
||||
@property (nonatomic) NSLayoutConstraint *readMarkerViewTopConstraint;
|
||||
@property (nonatomic) NSLayoutConstraint *readMarkerViewLeadingConstraint;
|
||||
@property (nonatomic) NSLayoutConstraint *readMarkerViewTrailingConstraint;
|
||||
@property (nonatomic) NSLayoutConstraint *readMarkerViewHeightConstraint;
|
||||
|
||||
/**
|
||||
The potential webview used to render an attachment (for example an animated gif).
|
||||
*/
|
||||
@property (nonatomic) WKWebView *attachmentWebView;
|
||||
|
||||
/**
|
||||
Called during the designated initializer of the UITableViewCell class to set the default
|
||||
properties values.
|
||||
|
||||
You should not call this method directly.
|
||||
|
||||
Subclasses can override this method as needed to customize the initialization.
|
||||
*/
|
||||
- (void)finalizeInit;
|
||||
|
||||
/**
|
||||
Handle progressView display.
|
||||
*/
|
||||
- (void)startProgressUI;
|
||||
- (void)updateProgressUI:(NSDictionary*)statisticsDict;
|
||||
|
||||
#pragma mark - Original Xib values
|
||||
|
||||
/**
|
||||
Get an original instance of the `MXKRoomBubbleTableViewCell` child class.
|
||||
|
||||
@return an instance of the child class caller which has the original Xib values.
|
||||
*/
|
||||
+ (MXKRoomBubbleTableViewCell*)cellWithOriginalXib;
|
||||
|
||||
/**
|
||||
Disable the handling of the long press on event (see kMXKRoomBubbleCellLongPressOnEvent). NO by default.
|
||||
|
||||
CAUTION: Changing this flag only impact the new created cells (existing 'MXKRoomBubbleTableViewCell' instances are unchanged).
|
||||
*/
|
||||
+ (void)disableLongPressGestureOnEvent:(BOOL)disable;
|
||||
|
||||
/**
|
||||
Method used during [MXKCellRendering render:] to check the provided `cellData`
|
||||
and prepare the protected `bubbleData`.
|
||||
Do not override it.
|
||||
|
||||
@param cellData the data object to render.
|
||||
*/
|
||||
- (void)prepareRender:(MXKCellData*)cellData;
|
||||
|
||||
/**
|
||||
Refresh the flair information added to the sender display name.
|
||||
*/
|
||||
- (void)renderSenderFlair;
|
||||
|
||||
/**
|
||||
Highlight text message related to a specific event in the displayed message.
|
||||
|
||||
@param eventId the id of the event to highlight (use nil to cancel highlighting).
|
||||
*/
|
||||
- (void)highlightTextMessageForEvent:(NSString*)eventId;
|
||||
|
||||
/**
|
||||
The top position of an event in the cell.
|
||||
|
||||
A cell can display several events. The method returns the vertical position of a given
|
||||
event in the cell.
|
||||
|
||||
@return the y position (in pixel) of the event in the cell.
|
||||
*/
|
||||
- (CGFloat)topPositionOfEvent:(NSString*)eventId;
|
||||
|
||||
/**
|
||||
The bottom position of an event in the cell.
|
||||
|
||||
A cell can display several events. The method returns the vertical position of the bottom part
|
||||
of a given event in the cell.
|
||||
|
||||
@return the y position (in pixel) of the bottom part of the event in the cell.
|
||||
*/
|
||||
- (CGFloat)bottomPositionOfEvent:(NSString*)eventId;
|
||||
|
||||
/**
|
||||
Restore `attachViewBottomConstraint` constant to default value.
|
||||
*/
|
||||
- (void)resetAttachmentViewBottomConstraintConstant;
|
||||
|
||||
/**
|
||||
Redeclare heightForCellData:withMaximumWidth: method from MXKCellRendering to use it as a class method in Swift and not a static method.
|
||||
*/
|
||||
+ (CGFloat)heightForCellData:(MXKCellData*)cellData withMaximumWidth:(CGFloat)maxWidth;
|
||||
|
||||
/**
|
||||
Setup outlets views. Useful to call when cell subclass does not use a xib otherwise this method is called automatically in `awakeFromNib`.
|
||||
*/
|
||||
- (void)setupViews;
|
||||
|
||||
/// Add temporary subview to `tmpSubviews` property.
|
||||
- (void)addTemporarySubview:(UIView*)subview;
|
||||
|
||||
@end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKTableViewCell.h"
|
||||
|
||||
#import "MXKCellRendering.h"
|
||||
|
||||
/**
|
||||
`MXKRoomIOSBubbleTableViewCell` instances mimic bubbles in the stock iOS messages application.
|
||||
*/
|
||||
@interface MXKRoomIOSBubbleTableViewCell : MXKTableViewCell <MXKCellRendering>
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomIOSBubbleTableViewCell.h"
|
||||
|
||||
#import "MXKRoomBubbleCellDataStoring.h"
|
||||
|
||||
@implementation MXKRoomIOSBubbleTableViewCell
|
||||
|
||||
- (void)render:(MXKCellData *)cellData
|
||||
{
|
||||
id<MXKRoomBubbleCellDataStoring> bubbleData = (id<MXKRoomBubbleCellDataStoring>)cellData;
|
||||
if (bubbleData)
|
||||
{
|
||||
self.textLabel.attributedText = bubbleData.attributedTextMessage;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.textLabel.text = @"";
|
||||
}
|
||||
|
||||
// Light custo for now... @TODO
|
||||
self.layer.cornerRadius = 20;
|
||||
self.backgroundColor = [UIColor blueColor];
|
||||
}
|
||||
|
||||
+ (CGFloat)heightForCellData:(MXKCellData *)cellData withMaximumWidth:(CGFloat)maxWidth
|
||||
{
|
||||
return 44;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomOutgoingBubbleTableViewCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomIOSBubbleTableViewCell` instances mimic bubbles in the stock iOS messages application.
|
||||
It is dedicated to outgoing messages.
|
||||
It subclasses `MXKRoomOutgoingBubbleTableViewCell` to take benefit of the available mechanic.
|
||||
*/
|
||||
@interface MXKRoomIOSOutgoingBubbleTableViewCell : MXKRoomOutgoingBubbleTableViewCell
|
||||
|
||||
/**
|
||||
The green bubble displayed in background.
|
||||
*/
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *bubbleImageView;
|
||||
|
||||
/**
|
||||
The width constraint on this backgroung green bubble.
|
||||
*/
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bubbleImageViewWidthConstraint;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomIOSOutgoingBubbleTableViewCell.h"
|
||||
|
||||
#import "MXKRoomBubbleCellData.h"
|
||||
|
||||
#import "MXEvent+MatrixKit.h"
|
||||
#import "MXKTools.h"
|
||||
|
||||
#import "NSBundle+MatrixKit.h"
|
||||
|
||||
#import "MXKImageView.h"
|
||||
|
||||
#define OUTGOING_BUBBLE_COLOR 0x00e34d
|
||||
|
||||
@implementation MXKRoomIOSOutgoingBubbleTableViewCell
|
||||
|
||||
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
|
||||
{
|
||||
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
|
||||
if (self)
|
||||
{
|
||||
// Create the strechable background bubble
|
||||
self.bubbleImageView.image = self.class.bubbleImage;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
}
|
||||
|
||||
- (void)render:(MXKCellData *)cellData
|
||||
{
|
||||
[super render:cellData];
|
||||
|
||||
// Reset values
|
||||
self.bubbleImageView.hidden = NO;
|
||||
|
||||
// Customise the data precomputed by the legacy classes
|
||||
// Replace black color in texts by the white color expected for outgoing messages.
|
||||
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.messageTextView.attributedText];
|
||||
|
||||
// Change all attributes one by one
|
||||
[attributedString enumerateAttributesInRange:NSMakeRange(0, attributedString.length) options:0 usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop)
|
||||
{
|
||||
|
||||
// Replace only black colored texts
|
||||
if (attrs[NSForegroundColorAttributeName] == self->bubbleData.eventFormatter.defaultTextColor)
|
||||
{
|
||||
|
||||
// By white
|
||||
NSMutableDictionary *newAttrs = [NSMutableDictionary dictionaryWithDictionary:attrs];
|
||||
newAttrs[NSForegroundColorAttributeName] = [UIColor whiteColor];
|
||||
|
||||
[attributedString setAttributes:newAttrs range:range];
|
||||
}
|
||||
}];
|
||||
|
||||
self.messageTextView.attributedText = attributedString;
|
||||
|
||||
// Update the bubble width to include the text view
|
||||
self.bubbleImageViewWidthConstraint.constant = bubbleData.contentSize.width + 17;
|
||||
|
||||
// Limit bubble width
|
||||
if (self.bubbleImageViewWidthConstraint.constant < 46)
|
||||
{
|
||||
self.bubbleImageViewWidthConstraint.constant = 46;
|
||||
}
|
||||
|
||||
// Mask the image with the bubble
|
||||
if (bubbleData.attachment && bubbleData.attachment.type != MXKAttachmentTypeFile && bubbleData.attachment.type != MXKAttachmentTypeAudio)
|
||||
{
|
||||
self.bubbleImageView.hidden = YES;
|
||||
|
||||
UIImageView *rightBubbleImageView = [[UIImageView alloc] initWithImage:self.class.bubbleImage];
|
||||
rightBubbleImageView.frame = CGRectMake(0, 0, self.bubbleImageViewWidthConstraint.constant, bubbleData.contentSize.height + self.attachViewTopConstraint.constant - 4);
|
||||
|
||||
self.attachmentView.layer.mask = rightBubbleImageView.layer;
|
||||
}
|
||||
}
|
||||
|
||||
+ (CGFloat)heightForCellData:(MXKCellData *)cellData withMaximumWidth:(CGFloat)maxWidth
|
||||
{
|
||||
CGFloat rowHeight = [super heightForCellData:cellData withMaximumWidth:maxWidth];
|
||||
|
||||
CGFloat height = self.cellWithOriginalXib.frame.size.height;
|
||||
|
||||
// Use the xib height as the minimal height
|
||||
if (rowHeight < height)
|
||||
{
|
||||
rowHeight = height;
|
||||
}
|
||||
|
||||
return rowHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
Create the strechable background bubble.
|
||||
|
||||
@return the bubble image.
|
||||
*/
|
||||
+ (UIImage *)bubbleImage
|
||||
{
|
||||
UIImage *rightBubbleImage = [NSBundle mxk_imageFromMXKAssetsBundleWithName:@"bubble_ios_messages_right"];
|
||||
|
||||
rightBubbleImage = [MXKTools paintImage:rightBubbleImage
|
||||
withColor:[MXKTools colorWithRGBValue:OUTGOING_BUBBLE_COLOR]];
|
||||
|
||||
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(17, 22, 17, 27);
|
||||
return [rightBubbleImage resizableImageWithCapInsets:edgeInsets];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,161 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="pad-g3-2YJ" customClass="MXKRoomIOSOutgoingBubbleTableViewCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="pad-g3-2YJ" id="fCg-ju-gnG">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="39"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Ktd-ms-tAu" userLabel="Bubble Image View">
|
||||
<rect key="frame" x="160" y="2" width="422" height="35"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="422" id="ptG-QV-Cix"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" text="text message" translatesAutoresizingMaskIntoConstraints="NO" id="tgO-Rv-C7R">
|
||||
<rect key="frame" x="74" y="3" width="495" height="36"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
||||
</textView>
|
||||
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="SIW-l4-PfI" userLabel="Attachment View" customClass="MXKImageView">
|
||||
<rect key="frame" x="160" y="2" width="422" height="35"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="192" id="iGr-e7-bde"/>
|
||||
</constraints>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="iGr-e7-bde"/>
|
||||
</mask>
|
||||
</variation>
|
||||
</view>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ZC1-hT-7fs">
|
||||
<rect key="frame" x="355" y="4" width="32" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="32" id="MOQ-Xi-18w"/>
|
||||
<constraint firstAttribute="height" constant="32" id="pGM-pf-SiP"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="Mqf-7a-bsm">
|
||||
<rect key="frame" x="361" y="10" width="20" height="20"/>
|
||||
</activityIndicatorView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LVJ-Av-zVs" userLabel="showHideDateTime">
|
||||
<rect key="frame" x="0.0" y="0.0" width="74" height="39"/>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="showHideDateTime:" destination="pad-g3-2YJ" eventType="touchUpInside" id="Ztw-z5-zlU"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="a51-cR-7FE" userLabel="bubbleInfoContainer">
|
||||
<rect key="frame" x="8" y="10" width="66" height="29"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="apW-hM-veR" userLabel="ProgressView">
|
||||
<rect key="frame" x="18" y="-16" width="100" height="71"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="text" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="4" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="DYj-Mb-me4" userLabel="Progress stats">
|
||||
<rect key="frame" x="0.0" y="61" width="100" height="10"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="8"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Oec-kb-Tsz" customClass="MXKPieChartView">
|
||||
<rect key="frame" x="30" y="0.0" width="40" height="41"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="40" id="6tZ-ag-7TT"/>
|
||||
<constraint firstAttribute="width" constant="40" id="duC-38-cLC"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstItem="Oec-kb-Tsz" firstAttribute="top" secondItem="apW-hM-veR" secondAttribute="top" id="49H-ch-qkC"/>
|
||||
<constraint firstAttribute="height" constant="70" id="GhG-zB-k3A"/>
|
||||
<constraint firstAttribute="centerX" secondItem="Oec-kb-Tsz" secondAttribute="centerX" id="KZy-2p-KaW"/>
|
||||
<constraint firstItem="DYj-Mb-me4" firstAttribute="leading" secondItem="apW-hM-veR" secondAttribute="leading" id="UxL-bV-5Ca"/>
|
||||
<constraint firstAttribute="bottom" secondItem="DYj-Mb-me4" secondAttribute="bottom" id="YFp-gQ-NFz"/>
|
||||
<constraint firstAttribute="width" constant="100" id="Zr4-5T-h9g"/>
|
||||
<constraint firstAttribute="trailing" secondItem="DYj-Mb-me4" secondAttribute="trailing" id="ehN-ME-1U1"/>
|
||||
<constraint firstAttribute="centerX" secondItem="DYj-Mb-me4" secondAttribute="centerX" id="nuq-lO-8pT"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerX" secondItem="Mqf-7a-bsm" secondAttribute="centerX" id="1b6-1l-hg0"/>
|
||||
<constraint firstItem="tgO-Rv-C7R" firstAttribute="leading" secondItem="LVJ-Av-zVs" secondAttribute="trailing" id="45B-ph-Sc3"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tgO-Rv-C7R" secondAttribute="bottom" id="7C3-Tl-mMq"/>
|
||||
<constraint firstItem="tgO-Rv-C7R" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="3" id="8Sy-eu-tYs"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="width" secondItem="Ktd-ms-tAu" secondAttribute="width" id="AjE-jd-r7q"/>
|
||||
<constraint firstAttribute="trailing" secondItem="SIW-l4-PfI" secondAttribute="trailing" constant="8" id="D8p-mV-ytb"/>
|
||||
<constraint firstItem="a51-cR-7FE" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" constant="8" id="E3x-h8-GPF"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="bottom" secondItem="Ktd-ms-tAu" secondAttribute="bottom" id="ET2-rD-uVQ"/>
|
||||
<constraint firstItem="LVJ-Av-zVs" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" id="Hve-E3-z5N"/>
|
||||
<constraint firstAttribute="bottom" secondItem="LVJ-Av-zVs" secondAttribute="bottom" id="IKr-Dc-HKz"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="Ktd-ms-tAu" secondAttribute="trailing" constant="10" id="LEJ-mA-aF4"/>
|
||||
<constraint firstItem="apW-hM-veR" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" constant="18" id="LFn-vp-m0v"/>
|
||||
<constraint firstItem="tgO-Rv-C7R" firstAttribute="leading" secondItem="a51-cR-7FE" secondAttribute="trailing" id="PJ9-Px-DPH"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="18" id="QDm-tP-KWa"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="top" secondItem="Ktd-ms-tAu" secondAttribute="top" id="W0E-eV-LGg"/>
|
||||
<constraint firstAttribute="bottom" secondItem="SIW-l4-PfI" secondAttribute="bottom" id="fMN-Th-SOT"/>
|
||||
<constraint firstItem="a51-cR-7FE" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="10" id="fQv-07-Pgx"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerY" secondItem="ZC1-hT-7fs" secondAttribute="centerY" id="ffI-vh-SW3"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Ktd-ms-tAu" secondAttribute="bottom" constant="2" id="haQ-G8-eZD"/>
|
||||
<constraint firstItem="tgO-Rv-C7R" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" constant="74" id="hwr-aa-TB4"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerX" secondItem="ZC1-hT-7fs" secondAttribute="centerX" id="jah-TA-P0P"/>
|
||||
<constraint firstItem="Ktd-ms-tAu" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="2" id="ltB-ic-svk"/>
|
||||
<constraint firstItem="LVJ-Av-zVs" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" id="pYO-hi-P72"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerY" secondItem="Mqf-7a-bsm" secondAttribute="centerY" id="sKJ-ny-LjM"/>
|
||||
<constraint firstAttribute="bottom" secondItem="a51-cR-7FE" secondAttribute="bottom" id="viZ-Sx-3RW"/>
|
||||
<constraint firstItem="apW-hM-veR" firstAttribute="centerY" secondItem="SIW-l4-PfI" secondAttribute="centerY" id="wmh-x1-U32"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tgO-Rv-C7R" secondAttribute="trailing" constant="31" id="xYz-lp-c7K"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="leading" secondItem="Ktd-ms-tAu" secondAttribute="leading" id="zvi-c3-uqP"/>
|
||||
</constraints>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="D8p-mV-ytb"/>
|
||||
<exclude reference="QDm-tP-KWa"/>
|
||||
<exclude reference="fMN-Th-SOT"/>
|
||||
</mask>
|
||||
</variation>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="Mqf-7a-bsm" id="toi-nL-eJa"/>
|
||||
<outlet property="attachViewTopConstraint" destination="QDm-tP-KWa" id="Ku6-FC-jqo"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="iGr-e7-bde" id="uD4-aU-1Ru"/>
|
||||
<outlet property="attachmentView" destination="SIW-l4-PfI" id="L4H-ub-pPI"/>
|
||||
<outlet property="bubbleImageView" destination="Ktd-ms-tAu" id="I0r-5F-rhe"/>
|
||||
<outlet property="bubbleImageViewWidthConstraint" destination="ptG-QV-Cix" id="TUH-dw-uqF"/>
|
||||
<outlet property="bubbleInfoContainer" destination="a51-cR-7FE" id="wrR-cU-DVm"/>
|
||||
<outlet property="bubbleInfoContainerTopConstraint" destination="fQv-07-Pgx" id="82c-KH-Wop"/>
|
||||
<outlet property="messageTextView" destination="tgO-Rv-C7R" id="LZ5-hQ-AbQ"/>
|
||||
<outlet property="msgTextViewBottomConstraint" destination="7C3-Tl-mMq" id="5Ff-xL-G1i"/>
|
||||
<outlet property="msgTextViewLeadingConstraint" destination="hwr-aa-TB4" id="A1E-ap-Ug6"/>
|
||||
<outlet property="msgTextViewTopConstraint" destination="8Sy-eu-tYs" id="7yx-oJ-KBP"/>
|
||||
<outlet property="msgTextViewTrailingConstraint" destination="xYz-lp-c7K" id="hc2-Cg-is4"/>
|
||||
<outlet property="playIconView" destination="ZC1-hT-7fs" id="zeH-8B-gxw"/>
|
||||
<outlet property="progressChartView" destination="Oec-kb-Tsz" id="uoq-6v-6Tm"/>
|
||||
<outlet property="progressView" destination="apW-hM-veR" id="Iy8-ca-hMi"/>
|
||||
<outlet property="statsLabel" destination="DYj-Mb-me4" id="CbG-5V-unO"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomBubbleTableViewCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomIncomingBubbleTableViewCell` inherits from 'MXKRoomBubbleTableViewCell' class in order to handle specific
|
||||
options related to incoming messages (like typing badge).
|
||||
|
||||
In order to optimize bubbles rendering, we advise to define a .xib for each layout.
|
||||
*/
|
||||
@interface MXKRoomIncomingBubbleTableViewCell : MXKRoomBubbleTableViewCell
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *typingBadge;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomIncomingBubbleTableViewCell.h"
|
||||
|
||||
#import "MXKRoomBubbleCellData.h"
|
||||
|
||||
#import "NSBundle+MatrixKit.h"
|
||||
|
||||
@implementation MXKRoomIncomingBubbleTableViewCell
|
||||
|
||||
- (void)finalizeInit
|
||||
{
|
||||
[super finalizeInit];
|
||||
self.readReceiptsAlignment = ReadReceiptAlignmentRight;
|
||||
}
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[super awakeFromNib];
|
||||
self.typingBadge.image = [NSBundle mxk_imageFromMXKAssetsBundleWithName:@"icon_keyboard"];
|
||||
}
|
||||
|
||||
- (void)render:(MXKCellData *)cellData
|
||||
{
|
||||
[super render:cellData];
|
||||
|
||||
if (bubbleData)
|
||||
{
|
||||
// Handle here typing badge (if any)
|
||||
if (self.typingBadge)
|
||||
{
|
||||
if (bubbleData.isTyping)
|
||||
{
|
||||
self.typingBadge.hidden = NO;
|
||||
[self.typingBadge.superview bringSubviewToFront:self.typingBadge];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.typingBadge.hidden = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didEndDisplay
|
||||
{
|
||||
[super didEndDisplay];
|
||||
self.readReceiptsAlignment = ReadReceiptAlignmentRight;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomBubbleTableViewCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomOutgoingBubbleTableViewCell` inherits from 'MXKRoomBubbleTableViewCell' class in order to handle specific
|
||||
options related to outgoing messages (like unsent labels, upload progress in case of attachment).
|
||||
|
||||
In order to optimize bubbles rendering, we advise to define a .xib for each layout.
|
||||
*/
|
||||
@interface MXKRoomOutgoingBubbleTableViewCell : MXKRoomBubbleTableViewCell
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomOutgoingBubbleTableViewCell.h"
|
||||
|
||||
#import "MXEvent+MatrixKit.h"
|
||||
|
||||
#import "NSBundle+Matrixkit.h"
|
||||
|
||||
#import "MXKRoomBubbleCellData.h"
|
||||
|
||||
#import "MXKSwiftHeader.h"
|
||||
|
||||
@implementation MXKRoomOutgoingBubbleTableViewCell
|
||||
|
||||
- (void)render:(MXKCellData *)cellData
|
||||
{
|
||||
[super render:cellData];
|
||||
|
||||
if (bubbleData)
|
||||
{
|
||||
// Add unsent label for failed components (except if the app customizes it)
|
||||
if (self.bubbleInfoContainer && (bubbleData.useCustomUnsentButton == NO))
|
||||
{
|
||||
for (MXKRoomBubbleComponent *component in bubbleData.bubbleComponents)
|
||||
{
|
||||
if (component.event.sentState == MXEventSentStateFailed)
|
||||
{
|
||||
UIButton *unsentButton = [[UIButton alloc] initWithFrame:CGRectMake(0, component.position.y, 58 , 20)];
|
||||
|
||||
[unsentButton setTitle:[MatrixKitL10n unsent] forState:UIControlStateNormal];
|
||||
[unsentButton setTitle:[MatrixKitL10n unsent] forState:UIControlStateSelected];
|
||||
[unsentButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
|
||||
[unsentButton setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
|
||||
|
||||
unsentButton.backgroundColor = [UIColor whiteColor];
|
||||
unsentButton.titleLabel.font = [UIFont systemFontOfSize:14];
|
||||
|
||||
[unsentButton addTarget:self action:@selector(onResendToggle:) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
[self.bubbleInfoContainer addSubview:unsentButton];
|
||||
self.bubbleInfoContainer.hidden = NO;
|
||||
self.bubbleInfoContainer.userInteractionEnabled = YES;
|
||||
|
||||
// ensure that bubbleInfoContainer is at front to catch the tap event
|
||||
[self.bubbleInfoContainer.superview bringSubviewToFront:self.bubbleInfoContainer];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didEndDisplay
|
||||
{
|
||||
[super didEndDisplay];
|
||||
|
||||
self.bubbleInfoContainer.userInteractionEnabled = NO;
|
||||
}
|
||||
|
||||
#pragma mark - User actions
|
||||
|
||||
- (IBAction)onResendToggle:(id)sender
|
||||
{
|
||||
if ([sender isKindOfClass:[UIButton class]] && self.delegate)
|
||||
{
|
||||
MXEvent *selectedEvent = nil;
|
||||
|
||||
NSArray *bubbleComponents = bubbleData.bubbleComponents;
|
||||
|
||||
if (bubbleComponents.count == 1)
|
||||
{
|
||||
MXKRoomBubbleComponent *component = [bubbleComponents firstObject];
|
||||
selectedEvent = component.event;
|
||||
}
|
||||
else if (bubbleComponents.count)
|
||||
{
|
||||
// Here the selected view is a textView (attachment has no more than one component)
|
||||
|
||||
// Look for the selected component
|
||||
UIButton *unsentButton = (UIButton *)sender;
|
||||
for (MXKRoomBubbleComponent *component in bubbleComponents)
|
||||
{
|
||||
// Ignore components without display.
|
||||
if (!component.attributedTextMessage)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unsentButton.frame.origin.y == component.position.y)
|
||||
{
|
||||
selectedEvent = component.event;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedEvent)
|
||||
{
|
||||
[self.delegate cell:self didRecognizeAction:kMXKRoomBubbleCellUnsentButtonPressed userInfo:@{kMXKRoomBubbleCellEventKey:selectedEvent}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2017 Vector Creations 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 "MXKRoomBubbleTableViewCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomEmptyBubbleTableViewCell` displays an empty bubbles without user's information.
|
||||
This kind of bubble may be used to localize an event without display in the room history.
|
||||
*/
|
||||
@interface MXKRoomEmptyBubbleTableViewCell : MXKRoomBubbleTableViewCell
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2017 Vector Creations 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 "MXKRoomEmptyBubbleTableViewCell.h"
|
||||
|
||||
@implementation MXKRoomEmptyBubbleTableViewCell
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12120" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
|
||||
<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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="pad-g3-2YJ" customClass="MXKRoomEmptyBubbleTableViewCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="8"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="pad-g3-2YJ" id="fCg-ju-gnG">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="7"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomIncomingBubbleTableViewCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomIncomingAttachmentBubbleCell` displays incoming attachment bubbles with sender's information.
|
||||
*/
|
||||
@interface MXKRoomIncomingAttachmentBubbleCell : MXKRoomIncomingBubbleTableViewCell
|
||||
|
||||
@end
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomIncomingAttachmentBubbleCell.h"
|
||||
|
||||
@implementation MXKRoomIncomingAttachmentBubbleCell
|
||||
|
||||
@end
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="WmY-Jw-mqv" customClass="MXKRoomIncomingAttachmentBubbleCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="49"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="hgp-Z5-rAj" userLabel="Picture View" customClass="MXKImageView">
|
||||
<rect key="frame" x="8" y="5" width="40" height="40"/>
|
||||
<color key="backgroundColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="40" id="NQk-ck-Lo8"/>
|
||||
<constraint firstAttribute="height" constant="40" id="dNT-QU-CUG"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="zwq-eh-8Fb" userLabel="typingBadge">
|
||||
<rect key="frame" x="5" y="0.0" width="20" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="20" id="7ni-rb-ovL"/>
|
||||
<constraint firstAttribute="height" constant="20" id="mcu-rQ-hnj"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="User name:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="8" translatesAutoresizingMaskIntoConstraints="NO" id="q9c-0p-QyP">
|
||||
<rect key="frame" x="51" y="3" width="480" height="20"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" placeholder="YES" id="5ZO-W1-tS2"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="13"/>
|
||||
<color key="textColor" red="0.33333333333333331" green="0.33333333333333331" blue="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView">
|
||||
<rect key="frame" x="51" y="18" width="192" height="23"/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="192" id="9zO-jU-qTb"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="23" id="C5F-6D-LZx"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="K9X-gn-noF" userLabel="File Type Image View">
|
||||
<rect key="frame" x="51" y="18" width="32" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="32" id="OE8-oh-B7Q"/>
|
||||
<constraint firstAttribute="height" constant="32" id="jJB-zj-fbT"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Cot-3X-2cU" userLabel="Play Icon Image View">
|
||||
<rect key="frame" x="131" y="14" width="32" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="32" id="8io-Wk-GzF"/>
|
||||
<constraint firstAttribute="width" constant="32" id="aeJ-j3-rfX"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kwd-hP-feC" userLabel="showHideDateTime">
|
||||
<rect key="frame" x="531" y="0.0" width="69" height="49"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="69" id="9vA-4g-EE5"/>
|
||||
</constraints>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="showHideDateTime:" destination="WmY-Jw-mqv" eventType="touchUpInside" id="jYV-nj-p60"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW" userLabel="bubbleInfoContainer">
|
||||
<rect key="frame" x="531" y="18" width="61" height="31"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="61" id="tLr-6k-ArA"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView">
|
||||
<rect key="frame" x="487" y="-5" width="100" height="70"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="rate" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="4" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="eU5-iK-u8i" userLabel="Progress stats">
|
||||
<rect key="frame" x="0.0" y="60" width="100" height="10"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="8"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hJj-TC-pxK" customClass="MXKPieChartView">
|
||||
<rect key="frame" x="30" y="0.0" width="40" height="40"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="40" id="Cpt-s4-tlK"/>
|
||||
<constraint firstAttribute="height" constant="40" id="Jb4-9E-tG0"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/>
|
||||
<constraint firstAttribute="centerX" secondItem="eU5-iK-u8i" secondAttribute="centerX" id="APi-aE-mLc"/>
|
||||
<constraint firstItem="eU5-iK-u8i" firstAttribute="leading" secondItem="fdx-qs-8en" secondAttribute="leading" id="Njw-3a-E9Y"/>
|
||||
<constraint firstAttribute="bottom" secondItem="eU5-iK-u8i" secondAttribute="bottom" id="QMO-g9-QVE"/>
|
||||
<constraint firstAttribute="centerX" secondItem="hJj-TC-pxK" secondAttribute="centerX" id="laR-Vg-ol3"/>
|
||||
<constraint firstItem="hJj-TC-pxK" firstAttribute="top" secondItem="fdx-qs-8en" secondAttribute="top" id="ovD-8p-4dP"/>
|
||||
<constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/>
|
||||
<constraint firstAttribute="trailing" secondItem="eU5-iK-u8i" secondAttribute="trailing" id="teG-8q-BOX"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GGt-zb-6zg">
|
||||
<rect key="frame" x="48" y="0.0" width="486" height="26"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="hgp-Z5-rAj" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="5" id="2Ih-ga-N9s"/>
|
||||
<constraint firstItem="kwd-hP-feC" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" id="5bB-HV-WAA"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="hgp-Z5-rAj" secondAttribute="trailing" constant="3" id="6mM-Ag-m0K"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="18" id="96U-67-5TP"/>
|
||||
<constraint firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" constant="69" id="Bkh-h2-JOQ"/>
|
||||
<constraint firstItem="GGt-zb-6zg" firstAttribute="leading" secondItem="q9c-0p-QyP" secondAttribute="leading" constant="-3" id="CsE-Bf-Wq7"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/>
|
||||
<constraint firstItem="q9c-0p-QyP" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="3" id="Ixr-7h-f8j"/>
|
||||
<constraint firstItem="GGt-zb-6zg" firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" constant="3" id="Ku9-ad-hb4"/>
|
||||
<constraint firstAttribute="bottom" secondItem="kwd-hP-feC" secondAttribute="bottom" id="LQg-cI-Nkn"/>
|
||||
<constraint firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" constant="8" id="SHN-tC-zsJ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="IOg-Kt-8vW" secondAttribute="bottom" id="TPw-iE-nii"/>
|
||||
<constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="18" id="XSL-TG-m62"/>
|
||||
<constraint firstItem="q9c-0p-QyP" firstAttribute="leading" secondItem="hgp-Z5-rAj" secondAttribute="trailing" constant="3" id="YWK-C2-15w"/>
|
||||
<constraint firstItem="GGt-zb-6zg" firstAttribute="top" secondItem="q9c-0p-QyP" secondAttribute="top" constant="-3" id="cqf-j2-9vP"/>
|
||||
<constraint firstItem="zwq-eh-8Fb" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="5" id="dgK-4e-UuE"/>
|
||||
<constraint firstAttribute="trailing" secondItem="kwd-hP-feC" secondAttribute="trailing" id="f2V-Ka-kU3"/>
|
||||
<constraint firstAttribute="trailing" secondItem="IOg-Kt-8vW" secondAttribute="trailing" constant="8" id="hQV-lO-7aQ"/>
|
||||
<constraint firstItem="GGt-zb-6zg" firstAttribute="bottom" secondItem="q9c-0p-QyP" secondAttribute="bottom" constant="3" id="kYd-0y-Rcu"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="K9X-gn-noF" secondAttribute="leading" id="p93-5h-lvW"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/>
|
||||
<constraint firstItem="zwq-eh-8Fb" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" id="tUd-UR-lzA"/>
|
||||
<constraint firstItem="hgp-Z5-rAj" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="8" id="tuw-aU-ncu"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="fdx-qs-8en" secondAttribute="centerY" id="v0F-Ts-14P"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/>
|
||||
<constraint firstAttribute="trailing" secondItem="fdx-qs-8en" secondAttribute="trailing" constant="13" id="xKk-Gz-moE"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="attachViewBottomConstraint" destination="SHN-tC-zsJ" id="cG0-a7-eHa"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="C5F-6D-LZx" id="frk-Ox-WbA"/>
|
||||
<outlet property="attachViewTopConstraint" destination="96U-67-5TP" id="Ugm-cH-32E"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="9zO-jU-qTb" id="fOO-VW-fe1"/>
|
||||
<outlet property="attachmentView" destination="5IE-JS-uf3" id="imT-1z-hR1"/>
|
||||
<outlet property="bubbleInfoContainer" destination="IOg-Kt-8vW" id="TAw-QY-Y9e"/>
|
||||
<outlet property="bubbleInfoContainerTopConstraint" destination="XSL-TG-m62" id="qVf-vJ-4aP"/>
|
||||
<outlet property="fileTypeIconView" destination="K9X-gn-noF" id="4Pj-bc-3gk"/>
|
||||
<outlet property="pictureView" destination="hgp-Z5-rAj" id="rKM-QG-RJN"/>
|
||||
<outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/>
|
||||
<outlet property="progressChartView" destination="hJj-TC-pxK" id="Zz3-s5-Qqr"/>
|
||||
<outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/>
|
||||
<outlet property="statsLabel" destination="eU5-iK-u8i" id="MSm-kU-RSY"/>
|
||||
<outlet property="typingBadge" destination="zwq-eh-8Fb" id="4vs-Dk-vWt"/>
|
||||
<outlet property="userNameLabel" destination="q9c-0p-QyP" id="JId-R7-LoM"/>
|
||||
<outlet property="userNameTapGestureMaskView" destination="GGt-zb-6zg" id="uV1-Jm-vLT"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomIncomingAttachmentBubbleCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell` displays incoming message bubbles without sender's information.
|
||||
*/
|
||||
@interface MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell : MXKRoomIncomingAttachmentBubbleCell
|
||||
|
||||
@end
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
|
||||
@implementation MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell
|
||||
|
||||
@end
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="WmY-Jw-mqv" customClass="MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="49"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView">
|
||||
<rect key="frame" x="51" y="8" width="192" height="33"/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="192" id="9zO-jU-qTb"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="33" id="Uqr-7d-0dv"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="K9X-gn-noF" userLabel="File Type Image View">
|
||||
<rect key="frame" x="51" y="8" width="32" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="32" id="OE8-oh-B7Q"/>
|
||||
<constraint firstAttribute="height" constant="32" id="jJB-zj-fbT"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Cot-3X-2cU" userLabel="Play Icon Image View">
|
||||
<rect key="frame" x="131" y="9" width="32" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="32" id="8io-Wk-GzF"/>
|
||||
<constraint firstAttribute="width" constant="32" id="aeJ-j3-rfX"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kwd-hP-feC" userLabel="showHideDateTime">
|
||||
<rect key="frame" x="531" y="0.0" width="69" height="49"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="69" id="9vA-4g-EE5"/>
|
||||
</constraints>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="showHideDateTime:" destination="WmY-Jw-mqv" eventType="touchUpInside" id="jYV-nj-p60"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW" userLabel="bubbleInfoContainer">
|
||||
<rect key="frame" x="531" y="8" width="61" height="41"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="61" id="tLr-6k-ArA"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView">
|
||||
<rect key="frame" x="487" y="-10" width="100" height="70"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="rate" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="4" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="eU5-iK-u8i" userLabel="Progress stats">
|
||||
<rect key="frame" x="0.0" y="60" width="100" height="10"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="8"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hJj-TC-pxK" customClass="MXKPieChartView">
|
||||
<rect key="frame" x="30" y="0.0" width="40" height="40"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="40" id="Cpt-s4-tlK"/>
|
||||
<constraint firstAttribute="height" constant="40" id="Jb4-9E-tG0"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/>
|
||||
<constraint firstAttribute="centerX" secondItem="eU5-iK-u8i" secondAttribute="centerX" id="APi-aE-mLc"/>
|
||||
<constraint firstItem="eU5-iK-u8i" firstAttribute="leading" secondItem="fdx-qs-8en" secondAttribute="leading" id="Njw-3a-E9Y"/>
|
||||
<constraint firstAttribute="bottom" secondItem="eU5-iK-u8i" secondAttribute="bottom" id="QMO-g9-QVE"/>
|
||||
<constraint firstAttribute="centerX" secondItem="hJj-TC-pxK" secondAttribute="centerX" id="laR-Vg-ol3"/>
|
||||
<constraint firstItem="hJj-TC-pxK" firstAttribute="top" secondItem="fdx-qs-8en" secondAttribute="top" id="ovD-8p-4dP"/>
|
||||
<constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/>
|
||||
<constraint firstAttribute="trailing" secondItem="eU5-iK-u8i" secondAttribute="trailing" id="teG-8q-BOX"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="kwd-hP-feC" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" id="5bB-HV-WAA"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="8" id="96U-67-5TP"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/>
|
||||
<constraint firstAttribute="bottom" secondItem="kwd-hP-feC" secondAttribute="bottom" id="LQg-cI-Nkn"/>
|
||||
<constraint firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" constant="8" id="SHN-tC-zsJ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="IOg-Kt-8vW" secondAttribute="bottom" id="TPw-iE-nii"/>
|
||||
<constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="8" id="XSL-TG-m62"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="51" id="bSL-lG-ued"/>
|
||||
<constraint firstAttribute="trailing" secondItem="kwd-hP-feC" secondAttribute="trailing" id="f2V-Ka-kU3"/>
|
||||
<constraint firstAttribute="trailing" secondItem="IOg-Kt-8vW" secondAttribute="trailing" constant="8" id="hQV-lO-7aQ"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="K9X-gn-noF" secondAttribute="leading" id="p93-5h-lvW"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="fdx-qs-8en" secondAttribute="centerY" id="v0F-Ts-14P"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/>
|
||||
<constraint firstAttribute="trailing" secondItem="fdx-qs-8en" secondAttribute="trailing" constant="13" id="xKk-Gz-moE"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="attachViewBottomConstraint" destination="SHN-tC-zsJ" id="cG0-a7-eHa"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="Uqr-7d-0dv" id="UIs-4K-np5"/>
|
||||
<outlet property="attachViewTopConstraint" destination="96U-67-5TP" id="Ugm-cH-32E"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="9zO-jU-qTb" id="fOO-VW-fe1"/>
|
||||
<outlet property="attachmentView" destination="5IE-JS-uf3" id="imT-1z-hR1"/>
|
||||
<outlet property="bubbleInfoContainer" destination="IOg-Kt-8vW" id="TAw-QY-Y9e"/>
|
||||
<outlet property="bubbleInfoContainerTopConstraint" destination="XSL-TG-m62" id="qVf-vJ-4aP"/>
|
||||
<outlet property="fileTypeIconView" destination="K9X-gn-noF" id="4Pj-bc-3gk"/>
|
||||
<outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/>
|
||||
<outlet property="progressChartView" destination="hJj-TC-pxK" id="Zz3-s5-Qqr"/>
|
||||
<outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/>
|
||||
<outlet property="statsLabel" destination="eU5-iK-u8i" id="MSm-kU-RSY"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
+3
-2
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
@@ -128,6 +128,7 @@
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="OrM-nA-kyg" id="Frc-ED-PlH"/>
|
||||
<outlet property="attachViewBottomConstraint" destination="SHN-tC-zsJ" id="cG0-a7-eHa"/>
|
||||
<outlet property="attachViewLeadingConstraint" destination="p93-5h-lvW" id="WRx-S5-r3M"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="C5F-6D-LZx" id="frk-Ox-WbA"/>
|
||||
<outlet property="attachViewTopConstraint" destination="96U-67-5TP" id="Ugm-cH-32E"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="9zO-jU-qTb" id="fOO-VW-fe1"/>
|
||||
|
||||
+3
-2
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
@@ -161,6 +161,7 @@
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="jmK-pe-WZd" id="F7y-hE-pcg"/>
|
||||
<outlet property="attachViewBottomConstraint" destination="SHN-tC-zsJ" id="cG0-a7-eHa"/>
|
||||
<outlet property="attachViewLeadingConstraint" destination="6mM-Ag-m0K" id="lG4-bl-Kio"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="C5F-6D-LZx" id="frk-Ox-WbA"/>
|
||||
<outlet property="attachViewTopConstraint" destination="96U-67-5TP" id="Ugm-cH-32E"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="9zO-jU-qTb" id="fOO-VW-fe1"/>
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
/**
|
||||
`RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell` displays outgoing attachment bubbles and pagination title but no sender name.
|
||||
*/
|
||||
@interface RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell : RoomOutgoingAttachmentWithPaginationTitleBubbleCell
|
||||
|
||||
@end
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
Copyright 2017 Vector Creations 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 "RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
|
||||
#import "ThemeService.h"
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@implementation RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell
|
||||
|
||||
- (void)customizeTableViewCellRendering
|
||||
{
|
||||
[super customizeTableViewCellRendering];
|
||||
|
||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
||||
}
|
||||
|
||||
@end
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
<?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" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="WmY-Jw-mqv" customClass="RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="120"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="120"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="SFg-55-RF4" userLabel="Pagination Title View">
|
||||
<rect key="frame" x="56" y="10" width="534" height="24"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wkY-7Y-sGw" userLabel="Pagination Label">
|
||||
<rect key="frame" x="0.0" y="0.0" width="524" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="18" id="PiZ-Ag-oxc"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<color key="textColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0kR-4b-Wav" userLabel="Pagination Separator View">
|
||||
<rect key="frame" x="0.0" y="23" width="534" height="1"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="PaginationTitleView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="wkY-7Y-sGw" secondAttribute="trailing" constant="10" id="4DU-xA-diS"/>
|
||||
<constraint firstItem="wkY-7Y-sGw" firstAttribute="top" secondItem="SFg-55-RF4" secondAttribute="top" id="6Cz-bj-kUg"/>
|
||||
<constraint firstItem="0kR-4b-Wav" firstAttribute="top" secondItem="wkY-7Y-sGw" secondAttribute="bottom" constant="5" id="K4B-zf-5x2"/>
|
||||
<constraint firstAttribute="height" constant="24" id="Qo9-cw-LCa"/>
|
||||
<constraint firstAttribute="trailing" secondItem="0kR-4b-Wav" secondAttribute="trailing" id="fnd-bR-QmB"/>
|
||||
<constraint firstAttribute="bottom" secondItem="0kR-4b-Wav" secondAttribute="bottom" id="pBK-pC-oCA"/>
|
||||
<constraint firstItem="0kR-4b-Wav" firstAttribute="leading" secondItem="SFg-55-RF4" secondAttribute="leading" id="rhH-Hz-w9J"/>
|
||||
<constraint firstItem="wkY-7Y-sGw" firstAttribute="leading" secondItem="SFg-55-RF4" secondAttribute="leading" id="uq9-MP-Dmm"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="hgp-Z5-rAj" userLabel="Picture View" customClass="MXKImageView">
|
||||
<rect key="frame" x="13" y="54" width="30" height="30"/>
|
||||
<color key="backgroundColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="PictureView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="30" id="NQk-ck-Lo8"/>
|
||||
<constraint firstAttribute="height" constant="30" id="dNT-QU-CUG"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView">
|
||||
<rect key="frame" x="56" y="45" width="192" height="65"/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="AttachmentView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="192" id="9zO-jU-qTb"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="34" id="C5F-6D-LZx"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="K9X-gn-noF" userLabel="File Type Image View">
|
||||
<rect key="frame" x="56" y="45" width="32" height="32"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="FileTypeImageView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="32" id="OE8-oh-B7Q"/>
|
||||
<constraint firstAttribute="height" constant="32" id="jJB-zj-fbT"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Cot-3X-2cU" userLabel="Play Icon Image View">
|
||||
<rect key="frame" x="136" y="61.5" width="32" height="32"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="PlayIconImageView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="32" id="8io-Wk-GzF"/>
|
||||
<constraint firstAttribute="width" constant="32" id="aeJ-j3-rfX"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="jmK-pe-WZd">
|
||||
<rect key="frame" x="142" y="67.5" width="20" height="20"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="accessibilityIdentifier" value="ActivityIndicator"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</activityIndicatorView>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW">
|
||||
<rect key="frame" x="515" y="54" width="70" height="66"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="70" id="tLr-6k-ArA"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView">
|
||||
<rect key="frame" x="487" y="50" width="100" height="70"/>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/>
|
||||
<constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3b7-4a-YL0">
|
||||
<rect key="frame" x="8" y="3" width="584" height="114"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="3b7-4a-YL0" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="topMargin" constant="-8" id="10i-70-PDz"/>
|
||||
<constraint firstItem="hgp-Z5-rAj" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="54" id="2Ih-ga-N9s"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="hgp-Z5-rAj" secondAttribute="trailing" constant="13" id="6mM-Ag-m0K"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="45" id="96U-67-5TP"/>
|
||||
<constraint firstAttribute="bottom" secondItem="fdx-qs-8en" secondAttribute="bottom" id="AeT-4F-mKp"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/>
|
||||
<constraint firstItem="SFg-55-RF4" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="56" id="I4N-5Q-LFe"/>
|
||||
<constraint firstItem="jmK-pe-WZd" firstAttribute="centerX" secondItem="5IE-JS-uf3" secondAttribute="centerX" id="IoK-NR-EyQ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" constant="10" id="SHN-tC-zsJ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="IOg-Kt-8vW" secondAttribute="bottom" id="TPw-iE-nii"/>
|
||||
<constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="54" id="XSL-TG-m62"/>
|
||||
<constraint firstItem="3b7-4a-YL0" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leadingMargin" constant="-8" id="aGh-ad-trR"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="3b7-4a-YL0" secondAttribute="trailing" constant="-8" id="abE-n9-N8T"/>
|
||||
<constraint firstAttribute="trailing" secondItem="IOg-Kt-8vW" secondAttribute="trailing" constant="15" id="hQV-lO-7aQ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="SFg-55-RF4" secondAttribute="trailing" constant="10" id="jvR-oT-EQF"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="K9X-gn-noF" secondAttribute="leading" id="p93-5h-lvW"/>
|
||||
<constraint firstItem="jmK-pe-WZd" firstAttribute="centerY" secondItem="5IE-JS-uf3" secondAttribute="centerY" id="qqJ-jh-rGK"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/>
|
||||
<constraint firstItem="hgp-Z5-rAj" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="13" id="tuw-aU-ncu"/>
|
||||
<constraint firstItem="SFg-55-RF4" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="wJX-7V-bJB"/>
|
||||
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="3b7-4a-YL0" secondAttribute="bottom" constant="-8" id="wpa-8Z-Gy3"/>
|
||||
<constraint firstAttribute="trailing" secondItem="fdx-qs-8en" secondAttribute="trailing" constant="13" id="xKk-Gz-moE"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="RoomBubbleCell"/>
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="jmK-pe-WZd" id="F7y-hE-pcg"/>
|
||||
<outlet property="attachViewBottomConstraint" destination="SHN-tC-zsJ" id="cG0-a7-eHa"/>
|
||||
<outlet property="attachViewLeadingConstraint" destination="6mM-Ag-m0K" id="lG4-bl-Kio"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="C5F-6D-LZx" id="frk-Ox-WbA"/>
|
||||
<outlet property="attachViewTopConstraint" destination="96U-67-5TP" id="Ugm-cH-32E"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="9zO-jU-qTb" id="fOO-VW-fe1"/>
|
||||
<outlet property="attachmentView" destination="5IE-JS-uf3" id="imT-1z-hR1"/>
|
||||
<outlet property="bubbleInfoContainer" destination="IOg-Kt-8vW" id="TAw-QY-Y9e"/>
|
||||
<outlet property="bubbleInfoContainerTopConstraint" destination="XSL-TG-m62" id="qVf-vJ-4aP"/>
|
||||
<outlet property="bubbleOverlayContainer" destination="3b7-4a-YL0" id="KNb-h4-YHD"/>
|
||||
<outlet property="fileTypeIconView" destination="K9X-gn-noF" id="4Pj-bc-3gk"/>
|
||||
<outlet property="paginationLabel" destination="wkY-7Y-sGw" id="9Uh-tX-t0I"/>
|
||||
<outlet property="paginationSeparatorView" destination="0kR-4b-Wav" id="c7x-Sh-aj6"/>
|
||||
<outlet property="paginationTitleView" destination="SFg-55-RF4" id="mbP-6I-gOn"/>
|
||||
<outlet property="pictureView" destination="hgp-Z5-rAj" id="rKM-QG-RJN"/>
|
||||
<outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/>
|
||||
<outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-26" y="113"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
+3
-2
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
@@ -95,6 +95,7 @@
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="8Bq-Mk-bN8" id="cbT-lK-yjP"/>
|
||||
<outlet property="attachViewBottomConstraint" destination="SHN-tC-zsJ" id="cG0-a7-eHa"/>
|
||||
<outlet property="attachViewLeadingConstraint" destination="bSL-lG-ued" id="M5E-Ot-73d"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="Uqr-7d-0dv" id="UIs-4K-np5"/>
|
||||
<outlet property="attachViewTopConstraint" destination="96U-67-5TP" id="Ugm-cH-32E"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="9zO-jU-qTb" id="fOO-VW-fe1"/>
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomOutgoingBubbleTableViewCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomOutgoingAttachmentBubbleCell` displays outgoing attachment bubbles.
|
||||
*/
|
||||
@interface MXKRoomOutgoingAttachmentBubbleCell : MXKRoomOutgoingBubbleTableViewCell
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
|
||||
|
||||
@end
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
Copyright 2018 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 "MXKRoomOutgoingAttachmentBubbleCell.h"
|
||||
|
||||
#import "MXEvent+MatrixKit.h"
|
||||
|
||||
#import "MXKRoomBubbleCellData.h"
|
||||
#import "MXKImageView.h"
|
||||
#import "MXKPieChartView.h"
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@implementation MXKRoomOutgoingAttachmentBubbleCell
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self stopAnimating];
|
||||
}
|
||||
|
||||
- (void)setupViews
|
||||
{
|
||||
[super setupViews];
|
||||
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
[timelineConfiguration.currentStyle.cellLayoutUpdater setupLayoutForOutgoingFileAttachmentCell:self];
|
||||
}
|
||||
|
||||
- (void)render:(MXKCellData *)cellData
|
||||
{
|
||||
[super render:cellData];
|
||||
|
||||
if (bubbleData)
|
||||
{
|
||||
// Do not display activity indicator on outgoing attachments (These attachments are supposed to be stored locally)
|
||||
// Some download may append to retrieve the actual thumbnail after posting an image.
|
||||
self.attachmentView.hideActivityIndicator = YES;
|
||||
|
||||
// Check if the attachment is uploading
|
||||
MXKRoomBubbleComponent *component = bubbleData.bubbleComponents.firstObject;
|
||||
if (component.event.sentState == MXEventSentStatePreparing || component.event.sentState == MXEventSentStateEncrypting || component.event.sentState == MXEventSentStateUploading)
|
||||
{
|
||||
// Retrieve the uploadId embedded in the fake url
|
||||
bubbleData.uploadId = component.event.content[@"url"];
|
||||
|
||||
self.attachmentView.alpha = 0.5;
|
||||
|
||||
// Start showing upload progress
|
||||
[self startUploadAnimating];
|
||||
}
|
||||
else if (component.event.sentState == MXEventSentStateSending)
|
||||
{
|
||||
self.attachmentView.alpha = 0.5;
|
||||
[self.activityIndicator startAnimating];
|
||||
}
|
||||
else if (component.event.sentState == MXEventSentStateFailed)
|
||||
{
|
||||
self.attachmentView.alpha = 0.5;
|
||||
[self.activityIndicator stopAnimating];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.attachmentView.alpha = 1;
|
||||
[self.activityIndicator stopAnimating];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didEndDisplay
|
||||
{
|
||||
[super didEndDisplay];
|
||||
|
||||
// Hide potential loading wheel
|
||||
[self stopAnimating];
|
||||
}
|
||||
|
||||
-(void)startUploadAnimating
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXMediaLoaderStateDidChangeNotification object:nil];
|
||||
|
||||
[self.activityIndicator startAnimating];
|
||||
|
||||
MXMediaLoader *uploader = [MXMediaManager existingUploaderWithId:bubbleData.uploadId];
|
||||
if (uploader)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaLoaderStateDidChange:) name:kMXMediaLoaderStateDidChangeNotification object:uploader];
|
||||
|
||||
if (uploader.statisticsDict)
|
||||
{
|
||||
[self.activityIndicator stopAnimating];
|
||||
[self updateProgressUI:uploader.statisticsDict];
|
||||
|
||||
// Check whether the upload is ended
|
||||
if (self.progressChartView.progress == 1.0)
|
||||
{
|
||||
[self stopAnimating];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.progressView.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
-(void)stopAnimating
|
||||
{
|
||||
self.progressView.hidden = YES;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXMediaLoaderStateDidChangeNotification object:nil];
|
||||
[self.activityIndicator stopAnimating];
|
||||
}
|
||||
|
||||
- (void)onMediaLoaderStateDidChange:(NSNotification *)notif
|
||||
{
|
||||
MXMediaLoader *loader = (MXMediaLoader*)notif.object;
|
||||
|
||||
// Consider only the progress of the current upload.
|
||||
if ([loader.uploadId isEqualToString:bubbleData.uploadId])
|
||||
{
|
||||
switch (loader.state) {
|
||||
case MXMediaLoaderStateUploadInProgress:
|
||||
{
|
||||
[self.activityIndicator stopAnimating];
|
||||
[self updateProgressUI:loader.statisticsDict];
|
||||
|
||||
// the upload is ended
|
||||
if (self.progressChartView.progress == 1.0)
|
||||
{
|
||||
[self stopAnimating];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="pad-g3-2YJ" customClass="MXKRoomOutgoingAttachmentBubbleCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="pad-g3-2YJ" id="fCg-ju-gnG">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="49"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="ezT-Dl-ESR" userLabel="Picture View" customClass="MXKImageView">
|
||||
<rect key="frame" x="552" y="5" width="40" height="40"/>
|
||||
<color key="backgroundColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="40" id="JHc-dD-geb"/>
|
||||
<constraint firstAttribute="height" constant="40" id="lFb-Jo-C7R"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="SIW-l4-PfI" userLabel="Attachment View" customClass="MXKImageView">
|
||||
<rect key="frame" x="357" y="18" width="192" height="23"/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="192" id="iGr-e7-bde"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="23" id="kGW-IH-XnB"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="KGx-6M-GER" userLabel="File Type Image View">
|
||||
<rect key="frame" x="357" y="18" width="32" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="32" id="QGB-Md-MLn"/>
|
||||
<constraint firstAttribute="width" constant="32" id="h7Q-f3-gtz"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ZC1-hT-7fs" userLabel="Play Icon Image View">
|
||||
<rect key="frame" x="437" y="14" width="32" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="32" id="MOQ-Xi-18w"/>
|
||||
<constraint firstAttribute="height" constant="32" id="pGM-pf-SiP"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="Mqf-7a-bsm">
|
||||
<rect key="frame" x="443" y="20" width="20" height="20"/>
|
||||
</activityIndicatorView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LVJ-Av-zVs" userLabel="showHideDateTime">
|
||||
<rect key="frame" x="0.0" y="0.0" width="69" height="49"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="69" id="ghQ-Qb-BBg"/>
|
||||
</constraints>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="showHideDateTime:" destination="pad-g3-2YJ" eventType="touchUpInside" id="Ztw-z5-zlU"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="a51-cR-7FE" userLabel="bubbleInfoContainer">
|
||||
<rect key="frame" x="8" y="18" width="61" height="31"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="61" id="fDy-iL-hrD"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="apW-hM-veR" userLabel="ProgressView">
|
||||
<rect key="frame" x="18" y="-5" width="100" height="70"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="text" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="4" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="DYj-Mb-me4" userLabel="Progress stats">
|
||||
<rect key="frame" x="0.0" y="60" width="100" height="10"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="8"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Oec-kb-Tsz" customClass="MXKPieChartView">
|
||||
<rect key="frame" x="30" y="0.0" width="40" height="40"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="40" id="6tZ-ag-7TT"/>
|
||||
<constraint firstAttribute="width" constant="40" id="duC-38-cLC"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstItem="Oec-kb-Tsz" firstAttribute="top" secondItem="apW-hM-veR" secondAttribute="top" id="49H-ch-qkC"/>
|
||||
<constraint firstAttribute="height" constant="70" id="GhG-zB-k3A"/>
|
||||
<constraint firstAttribute="centerX" secondItem="Oec-kb-Tsz" secondAttribute="centerX" id="KZy-2p-KaW"/>
|
||||
<constraint firstItem="DYj-Mb-me4" firstAttribute="leading" secondItem="apW-hM-veR" secondAttribute="leading" id="UxL-bV-5Ca"/>
|
||||
<constraint firstAttribute="bottom" secondItem="DYj-Mb-me4" secondAttribute="bottom" id="YFp-gQ-NFz"/>
|
||||
<constraint firstAttribute="width" constant="100" id="Zr4-5T-h9g"/>
|
||||
<constraint firstAttribute="trailing" secondItem="DYj-Mb-me4" secondAttribute="trailing" id="ehN-ME-1U1"/>
|
||||
<constraint firstAttribute="centerX" secondItem="DYj-Mb-me4" secondAttribute="centerX" id="nuq-lO-8pT"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerX" secondItem="Mqf-7a-bsm" secondAttribute="centerX" id="1b6-1l-hg0"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ezT-Dl-ESR" secondAttribute="trailing" constant="8" id="3Pd-Qy-Xva"/>
|
||||
<constraint firstItem="ezT-Dl-ESR" firstAttribute="leading" secondItem="SIW-l4-PfI" secondAttribute="trailing" constant="3" id="9z3-D2-2SS"/>
|
||||
<constraint firstItem="a51-cR-7FE" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" constant="8" id="E3x-h8-GPF"/>
|
||||
<constraint firstItem="LVJ-Av-zVs" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" id="Hve-E3-z5N"/>
|
||||
<constraint firstAttribute="bottom" secondItem="LVJ-Av-zVs" secondAttribute="bottom" id="IKr-Dc-HKz"/>
|
||||
<constraint firstItem="apW-hM-veR" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" constant="18" id="LFn-vp-m0v"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="18" id="QDm-tP-KWa"/>
|
||||
<constraint firstItem="ezT-Dl-ESR" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="5" id="aHl-KA-68x"/>
|
||||
<constraint firstAttribute="bottom" secondItem="SIW-l4-PfI" secondAttribute="bottom" constant="8" id="fMN-Th-SOT"/>
|
||||
<constraint firstItem="a51-cR-7FE" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="18" id="fQv-07-Pgx"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerY" secondItem="ZC1-hT-7fs" secondAttribute="centerY" id="ffI-vh-SW3"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="leading" secondItem="KGx-6M-GER" secondAttribute="leading" id="j1U-XX-IZW"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerX" secondItem="ZC1-hT-7fs" secondAttribute="centerX" id="jah-TA-P0P"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="top" secondItem="KGx-6M-GER" secondAttribute="top" id="loA-GI-HkT"/>
|
||||
<constraint firstItem="LVJ-Av-zVs" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" id="pYO-hi-P72"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerY" secondItem="Mqf-7a-bsm" secondAttribute="centerY" id="sKJ-ny-LjM"/>
|
||||
<constraint firstAttribute="bottom" secondItem="a51-cR-7FE" secondAttribute="bottom" id="viZ-Sx-3RW"/>
|
||||
<constraint firstItem="apW-hM-veR" firstAttribute="centerY" secondItem="SIW-l4-PfI" secondAttribute="centerY" id="wmh-x1-U32"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="Mqf-7a-bsm" id="toi-nL-eJa"/>
|
||||
<outlet property="attachViewBottomConstraint" destination="fMN-Th-SOT" id="WVk-1p-S0P"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="kGW-IH-XnB" id="97f-NR-EDv"/>
|
||||
<outlet property="attachViewTopConstraint" destination="QDm-tP-KWa" id="Ku6-FC-jqo"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="iGr-e7-bde" id="uD4-aU-1Ru"/>
|
||||
<outlet property="attachmentView" destination="SIW-l4-PfI" id="L4H-ub-pPI"/>
|
||||
<outlet property="bubbleInfoContainer" destination="a51-cR-7FE" id="wrR-cU-DVm"/>
|
||||
<outlet property="bubbleInfoContainerTopConstraint" destination="fQv-07-Pgx" id="82c-KH-Wop"/>
|
||||
<outlet property="fileTypeIconView" destination="KGx-6M-GER" id="MXF-4w-mY7"/>
|
||||
<outlet property="pictureView" destination="ezT-Dl-ESR" id="YsO-Kp-xaD"/>
|
||||
<outlet property="playIconView" destination="ZC1-hT-7fs" id="zeH-8B-gxw"/>
|
||||
<outlet property="progressChartView" destination="Oec-kb-Tsz" id="uoq-6v-6Tm"/>
|
||||
<outlet property="progressView" destination="apW-hM-veR" id="Iy8-ca-hMi"/>
|
||||
<outlet property="statsLabel" destination="DYj-Mb-me4" id="CbG-5V-unO"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomOutgoingAttachmentBubbleCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell` displays outgoing attachment with thumbnail, without user's name.
|
||||
*/
|
||||
@interface MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell : MXKRoomOutgoingAttachmentBubbleCell
|
||||
|
||||
@end
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
|
||||
@implementation MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell
|
||||
|
||||
@end
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="pad-g3-2YJ" customClass="MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="pad-g3-2YJ" id="fCg-ju-gnG">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="49"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="SIW-l4-PfI" userLabel="Attachment View" customClass="MXKImageView">
|
||||
<rect key="frame" x="357" y="8" width="192" height="33"/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="192" id="iGr-e7-bde"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="33" id="nSK-Ug-3Q4"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="KGx-6M-GER" userLabel="File Type Image View">
|
||||
<rect key="frame" x="357" y="8" width="32" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="32" id="QGB-Md-MLn"/>
|
||||
<constraint firstAttribute="width" constant="32" id="h7Q-f3-gtz"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ZC1-hT-7fs" userLabel="Play Icon Image View">
|
||||
<rect key="frame" x="437" y="9" width="32" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="32" id="MOQ-Xi-18w"/>
|
||||
<constraint firstAttribute="height" constant="32" id="pGM-pf-SiP"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="Mqf-7a-bsm">
|
||||
<rect key="frame" x="443" y="15" width="20" height="20"/>
|
||||
</activityIndicatorView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LVJ-Av-zVs" userLabel="showHideDateTime">
|
||||
<rect key="frame" x="0.0" y="0.0" width="69" height="49"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="69" id="ghQ-Qb-BBg"/>
|
||||
</constraints>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="showHideDateTime:" destination="pad-g3-2YJ" eventType="touchUpInside" id="Ztw-z5-zlU"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="a51-cR-7FE" userLabel="bubbleInfoContainer">
|
||||
<rect key="frame" x="8" y="8" width="61" height="41"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="61" id="fDy-iL-hrD"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="apW-hM-veR" userLabel="ProgressView">
|
||||
<rect key="frame" x="18" y="-10" width="100" height="70"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="text" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="4" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="DYj-Mb-me4" userLabel="Progress stats">
|
||||
<rect key="frame" x="0.0" y="60" width="100" height="10"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="8"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Oec-kb-Tsz" customClass="MXKPieChartView">
|
||||
<rect key="frame" x="30" y="0.0" width="40" height="40"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="40" id="6tZ-ag-7TT"/>
|
||||
<constraint firstAttribute="width" constant="40" id="duC-38-cLC"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstItem="Oec-kb-Tsz" firstAttribute="top" secondItem="apW-hM-veR" secondAttribute="top" id="49H-ch-qkC"/>
|
||||
<constraint firstAttribute="height" constant="70" id="GhG-zB-k3A"/>
|
||||
<constraint firstAttribute="centerX" secondItem="Oec-kb-Tsz" secondAttribute="centerX" id="KZy-2p-KaW"/>
|
||||
<constraint firstItem="DYj-Mb-me4" firstAttribute="leading" secondItem="apW-hM-veR" secondAttribute="leading" id="UxL-bV-5Ca"/>
|
||||
<constraint firstAttribute="bottom" secondItem="DYj-Mb-me4" secondAttribute="bottom" id="YFp-gQ-NFz"/>
|
||||
<constraint firstAttribute="width" constant="100" id="Zr4-5T-h9g"/>
|
||||
<constraint firstAttribute="trailing" secondItem="DYj-Mb-me4" secondAttribute="trailing" id="ehN-ME-1U1"/>
|
||||
<constraint firstAttribute="centerX" secondItem="DYj-Mb-me4" secondAttribute="centerX" id="nuq-lO-8pT"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerX" secondItem="Mqf-7a-bsm" secondAttribute="centerX" id="1b6-1l-hg0"/>
|
||||
<constraint firstItem="a51-cR-7FE" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" constant="8" id="E3x-h8-GPF"/>
|
||||
<constraint firstItem="LVJ-Av-zVs" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" id="Hve-E3-z5N"/>
|
||||
<constraint firstAttribute="bottom" secondItem="LVJ-Av-zVs" secondAttribute="bottom" id="IKr-Dc-HKz"/>
|
||||
<constraint firstItem="apW-hM-veR" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" constant="18" id="LFn-vp-m0v"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="8" id="QDm-tP-KWa"/>
|
||||
<constraint firstAttribute="bottom" secondItem="SIW-l4-PfI" secondAttribute="bottom" constant="8" id="fMN-Th-SOT"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerY" secondItem="ZC1-hT-7fs" secondAttribute="centerY" id="ffI-vh-SW3"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="leading" secondItem="KGx-6M-GER" secondAttribute="leading" id="j1U-XX-IZW"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerX" secondItem="ZC1-hT-7fs" secondAttribute="centerX" id="jah-TA-P0P"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="top" secondItem="KGx-6M-GER" secondAttribute="top" id="loA-GI-HkT"/>
|
||||
<constraint firstItem="LVJ-Av-zVs" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" id="pYO-hi-P72"/>
|
||||
<constraint firstItem="SIW-l4-PfI" firstAttribute="centerY" secondItem="Mqf-7a-bsm" secondAttribute="centerY" id="sKJ-ny-LjM"/>
|
||||
<constraint firstAttribute="bottom" secondItem="a51-cR-7FE" secondAttribute="bottom" id="viZ-Sx-3RW"/>
|
||||
<constraint firstAttribute="trailing" secondItem="SIW-l4-PfI" secondAttribute="trailing" constant="51" id="wgx-Zr-5R6"/>
|
||||
<constraint firstItem="apW-hM-veR" firstAttribute="centerY" secondItem="SIW-l4-PfI" secondAttribute="centerY" id="wmh-x1-U32"/>
|
||||
<constraint firstItem="a51-cR-7FE" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="8" id="xop-v3-Xh2"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="Mqf-7a-bsm" id="toi-nL-eJa"/>
|
||||
<outlet property="attachViewBottomConstraint" destination="fMN-Th-SOT" id="fw0-N9-RUj"/>
|
||||
<outlet property="attachViewMinHeightConstraint" destination="nSK-Ug-3Q4" id="rfM-Ha-vVp"/>
|
||||
<outlet property="attachViewTopConstraint" destination="QDm-tP-KWa" id="Ku6-FC-jqo"/>
|
||||
<outlet property="attachViewWidthConstraint" destination="iGr-e7-bde" id="uD4-aU-1Ru"/>
|
||||
<outlet property="attachmentView" destination="SIW-l4-PfI" id="L4H-ub-pPI"/>
|
||||
<outlet property="bubbleInfoContainer" destination="a51-cR-7FE" id="wrR-cU-DVm"/>
|
||||
<outlet property="fileTypeIconView" destination="KGx-6M-GER" id="MXF-4w-mY7"/>
|
||||
<outlet property="playIconView" destination="ZC1-hT-7fs" id="zeH-8B-gxw"/>
|
||||
<outlet property="progressChartView" destination="Oec-kb-Tsz" id="uoq-6v-6Tm"/>
|
||||
<outlet property="progressView" destination="apW-hM-veR" id="Iy8-ca-hMi"/>
|
||||
<outlet property="statsLabel" destination="DYj-Mb-me4" id="CbG-5V-unO"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -37,11 +37,17 @@ class LocationBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable
|
||||
|
||||
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)
|
||||
if locationContent.assetType == .user {
|
||||
let avatarViewData = AvatarViewData(matrixItemId: bubbleData.senderId,
|
||||
displayName: bubbleData.senderDisplayName,
|
||||
avatarUrl: bubbleData.senderAvatarUrl,
|
||||
mediaManager: bubbleData.mxSession.mediaManager,
|
||||
fallbackImage: .matrixItem(bubbleData.senderId, bubbleData.senderDisplayName))
|
||||
|
||||
locationView.displayLocation(location, userAvatarData: avatarViewData)
|
||||
} else {
|
||||
locationView.displayLocation(location)
|
||||
}
|
||||
}
|
||||
|
||||
override func setupViews() {
|
||||
|
||||
+1
-1
@@ -51,5 +51,5 @@ final class RoomBubbleCellLayout: NSObject {
|
||||
|
||||
static let threadSummaryViewTopMargin: CGFloat = 8.0
|
||||
static let threadSummaryViewHeight: CGFloat = 40.0
|
||||
static let fromThreadViewTopMargin: CGFloat = 8.0
|
||||
static let fromAThreadViewTopMargin: CGFloat = 8.0
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
/// RoomTimelineCellIdentifier represents room timeline cell identifiers.
|
||||
typedef NS_ENUM(NSUInteger, RoomTimelineCellIdentifier) {
|
||||
|
||||
RoomTimelineCellIdentifierUnknown,
|
||||
|
||||
// - Text message
|
||||
// -- Incoming
|
||||
// --- Clear
|
||||
RoomTimelineCellIdentifierIncomingTextMessage,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderName,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitleWithoutSenderName,
|
||||
// --- Encrypted
|
||||
RoomTimelineCellIdentifierIncomingTextMessageEncrypted,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderName,
|
||||
RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitleWithoutSenderName,
|
||||
// -- Outgoing
|
||||
// --- Clear
|
||||
RoomTimelineCellIdentifierOutgoingTextMessage,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderName,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitleWithoutSenderName,
|
||||
// --- Encrypted
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageEncrypted,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderName,
|
||||
RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitleWithoutSenderName,
|
||||
|
||||
// - Attachment
|
||||
// -- Incoming
|
||||
// --- Clear
|
||||
RoomTimelineCellIdentifierIncomingAttachment,
|
||||
RoomTimelineCellIdentifierIncomingAttachmentWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierIncomingAttachmentWithPaginationTitle,
|
||||
// --- Encrypted
|
||||
RoomTimelineCellIdentifierIncomingAttachmentEncrypted,
|
||||
RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithPaginationTitle,
|
||||
// -- Outgoing
|
||||
// --- Clear
|
||||
RoomTimelineCellIdentifierOutgoingAttachment,
|
||||
RoomTimelineCellIdentifierOutgoingAttachmentWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierOutgoingAttachmentWithPaginationTitle,
|
||||
// --- Encrypted
|
||||
RoomTimelineCellIdentifierOutgoingAttachmentEncrypted,
|
||||
RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithPaginationTitle,
|
||||
|
||||
// - Room membership
|
||||
RoomTimelineCellIdentifierMembership,
|
||||
RoomTimelineCellIdentifierMembershipWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierMembershipCollapsed,
|
||||
RoomTimelineCellIdentifierMembershipCollapsedWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierMembershipExpanded,
|
||||
RoomTimelineCellIdentifierMembershipExpandedWithPaginationTitle,
|
||||
|
||||
// - Key verification
|
||||
RoomTimelineCellIdentifierKeyVerificationIncomingRequestApproval,
|
||||
RoomTimelineCellIdentifierKeyVerificationIncomingRequestApprovalWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierKeyVerificationRequestStatus,
|
||||
RoomTimelineCellIdentifierKeyVerificationRequestStatusWithPaginationTitle,
|
||||
RoomTimelineCellIdentifierKeyVerificationConclusion,
|
||||
RoomTimelineCellIdentifierKeyVerificationConclusionWithPaginationTitle,
|
||||
|
||||
// - Room creation
|
||||
RoomTimelineCellIdentifierRoomCreationCollapsed,
|
||||
RoomTimelineCellIdentifierRoomCreationCollapsedWithPaginationTitle,
|
||||
|
||||
// - Call
|
||||
RoomTimelineCellIdentifierDirectCallStatus,
|
||||
RoomTimelineCellIdentifierGroupCallStatus,
|
||||
|
||||
// - Voice message
|
||||
RoomTimelineCellIdentifierVoiceMessage,
|
||||
RoomTimelineCellIdentifierVoiceMessageWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierVoiceMessageWithPaginationTitle,
|
||||
|
||||
// - Poll
|
||||
RoomTimelineCellIdentifierPoll,
|
||||
RoomTimelineCellIdentifierPollWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierPollWithPaginationTitle,
|
||||
|
||||
// - Location sharing
|
||||
RoomTimelineCellIdentifierLocation,
|
||||
RoomTimelineCellIdentifierLocationWithoutSenderInfo,
|
||||
RoomTimelineCellIdentifierLocationWithPaginationTitle,
|
||||
|
||||
// - Others
|
||||
RoomTimelineCellIdentifierEmpty,
|
||||
RoomTimelineCellIdentifierSelectedSticker,
|
||||
RoomTimelineCellIdentifierRoomPredecessor,
|
||||
RoomTimelineCellIdentifierRoomCreationIntro,
|
||||
RoomTimelineCellIdentifierTyping
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
/// RoomTimelineConfiguration enables to manage room timeline appearance configuration
|
||||
@objcMembers
|
||||
class RoomTimelineConfiguration: NSObject {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
static let shared = RoomTimelineConfiguration()
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
private(set) var currentStyle: RoomTimelineStyle
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(style: RoomTimelineStyle) {
|
||||
self.currentStyle = style
|
||||
|
||||
super.init()
|
||||
|
||||
self.registerThemeDidChange()
|
||||
}
|
||||
|
||||
convenience init(styleIdentifier: RoomTimelineStyleIdentifier) {
|
||||
|
||||
let style = type(of: self).style(for: styleIdentifier)
|
||||
self.init(style: style)
|
||||
}
|
||||
|
||||
convenience override init() {
|
||||
let styleIdentifier = RiotSettings.shared.roomTimelineStyleIdentifier
|
||||
self.init(styleIdentifier: styleIdentifier)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func updateStyle(_ roomTimelineStyle: RoomTimelineStyle) {
|
||||
self.currentStyle = roomTimelineStyle
|
||||
}
|
||||
|
||||
func updateStyle(withIdentifier identifier: RoomTimelineStyleIdentifier) {
|
||||
|
||||
let style = type(of: self).style(for: identifier)
|
||||
|
||||
self.updateStyle(style)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func registerThemeDidChange() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange(notification:)), name: .themeServiceDidChangeTheme, object: nil)
|
||||
|
||||
}
|
||||
|
||||
@objc private func themeDidChange(notification: Notification) {
|
||||
|
||||
guard let themeService = notification.object as? ThemeService else {
|
||||
return
|
||||
}
|
||||
|
||||
self.currentStyle.update(theme: themeService.theme)
|
||||
}
|
||||
|
||||
private class func style(for identifier: RoomTimelineStyleIdentifier) -> RoomTimelineStyle {
|
||||
|
||||
let roomTimelineStyle: RoomTimelineStyle
|
||||
|
||||
let theme = ThemeService.shared().theme
|
||||
|
||||
switch identifier {
|
||||
case .plain:
|
||||
roomTimelineStyle = PlainRoomTimelineStyle(theme: theme)
|
||||
case .bubble:
|
||||
roomTimelineStyle = BubbleRoomTimelineStyle(theme: theme)
|
||||
}
|
||||
|
||||
return roomTimelineStyle
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,6 @@
|
||||
@property (weak, nonatomic) IBOutlet UILabel *descriptionLabel;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *userNameLabelTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewLeadingConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *descriptionContainerViewBottomConstraint;
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
@objcMembers
|
||||
class BubbleRoomCellLayoutUpdater: RoomCellLayoutUpdating {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
private var theme: Theme
|
||||
|
||||
private var incomingColor: UIColor {
|
||||
return self.theme.colors.system
|
||||
}
|
||||
|
||||
private var outgoingColor: UIColor {
|
||||
return self.theme.colors.accent.withAlphaComponent(0.10)
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(theme: Theme) {
|
||||
self.theme = theme
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func updateLayoutIfNeeded(for cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) {
|
||||
|
||||
if cellData.isSenderCurrentUser {
|
||||
self.updateLayout(forOutgoingTextMessageCell: cell, andCellData: cellData)
|
||||
} else {
|
||||
self.updateLayout(forIncomingTextMessageCell: cell, andCellData: cellData)
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(forIncomingTextMessageCell cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) {
|
||||
|
||||
if let messageBubbleBackgroundView = cell.messageBubbleBackgroundView {
|
||||
|
||||
if self.canUseBubbleBackground(forCell: cell, withCellData: cellData) {
|
||||
|
||||
messageBubbleBackgroundView.isHidden = false
|
||||
|
||||
self.updateMessageBubbleBackgroundView(messageBubbleBackgroundView, withCell: cell, andCellData: cellData)
|
||||
} else {
|
||||
messageBubbleBackgroundView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(forOutgoingTextMessageCell cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) {
|
||||
|
||||
if let messageBubbleBackgroundView = cell.messageBubbleBackgroundView {
|
||||
|
||||
if self.canUseBubbleBackground(forCell: cell, withCellData: cellData) {
|
||||
|
||||
messageBubbleBackgroundView.isHidden = false
|
||||
|
||||
self.updateMessageBubbleBackgroundView(messageBubbleBackgroundView, withCell: cell, andCellData: cellData)
|
||||
} else {
|
||||
messageBubbleBackgroundView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setupLayout(forIncomingTextMessageCell cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
self.setupIncomingMessageTextViewMargins(for: cell)
|
||||
|
||||
self.addBubbleBackgroundViewToCell(cell, backgroundColor: self.incomingColor)
|
||||
|
||||
cell.setNeedsUpdateConstraints()
|
||||
}
|
||||
|
||||
func setupLayout(forOutgoingTextMessageCell cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
self.setupOutgoingMessageTextViewMargins(for: cell)
|
||||
|
||||
// Hide avatar view
|
||||
cell.pictureView?.isHidden = true
|
||||
|
||||
self.addBubbleBackgroundViewToCell(cell, backgroundColor: self.outgoingColor)
|
||||
|
||||
cell.setNeedsUpdateConstraints()
|
||||
}
|
||||
|
||||
func setupLayout(forOutgoingFileAttachmentCell cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
// Hide avatar view
|
||||
cell.pictureView?.isHidden = true
|
||||
|
||||
self.setupOutgoingFileAttachViewMargins(for: cell)
|
||||
}
|
||||
|
||||
// MARK: Themable
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
// MARK: Bubble background view
|
||||
|
||||
private func createBubbleBackgroundView(with backgroundColor: UIColor) -> RoomMessageBubbleBackgroundView {
|
||||
|
||||
let bubbleBackgroundView = RoomMessageBubbleBackgroundView()
|
||||
bubbleBackgroundView.backgroundColor = backgroundColor
|
||||
|
||||
return bubbleBackgroundView
|
||||
}
|
||||
|
||||
private func addBubbleBackgroundViewToCell(_ bubbleCell: MXKRoomBubbleTableViewCell, backgroundColor: UIColor) {
|
||||
|
||||
guard let messageTextView = bubbleCell.messageTextView else {
|
||||
return
|
||||
}
|
||||
|
||||
let topMargin: CGFloat = 0.0
|
||||
let leftMargin: CGFloat = 5.0
|
||||
let rightMargin: CGFloat = 45.0 // Add extra space for timestamp
|
||||
|
||||
let bubbleBackgroundView = self.createBubbleBackgroundView(with: backgroundColor)
|
||||
|
||||
bubbleCell.contentView.insertSubview(bubbleBackgroundView, at: 0)
|
||||
|
||||
let topAnchor = messageTextView.topAnchor
|
||||
let leadingAnchor = messageTextView.leadingAnchor
|
||||
let trailingAnchor = messageTextView.trailingAnchor
|
||||
|
||||
bubbleBackgroundView.updateHeight(messageTextView.frame.height)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
bubbleBackgroundView.topAnchor.constraint(equalTo: topAnchor, constant: topMargin),
|
||||
bubbleBackgroundView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: -leftMargin),
|
||||
bubbleBackgroundView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: rightMargin)
|
||||
])
|
||||
}
|
||||
|
||||
private func canUseBubbleBackground(forCell cell: MXKRoomBubbleTableViewCell, withCellData cellData: MXKRoomBubbleCellData) -> Bool {
|
||||
|
||||
guard let firstComponent = cellData.getFirstBubbleComponentWithDisplay(), let firstEvent = firstComponent.event else {
|
||||
return false
|
||||
}
|
||||
|
||||
switch firstEvent.eventType {
|
||||
case .roomMessage:
|
||||
if let messageTypeString = firstEvent.content["msgtype"] as? String {
|
||||
|
||||
let messageType = MXMessageType(identifier: messageTypeString)
|
||||
|
||||
switch messageType {
|
||||
case .text, .emote, .file:
|
||||
return true
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private func getTextMessageHeight(for cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) -> CGFloat? {
|
||||
|
||||
guard let roomBubbleCellData = cellData as? RoomBubbleCellData,
|
||||
let lastBubbleComponent = cellData.getLastBubbleComponentWithDisplay(),
|
||||
let firstComponent = roomBubbleCellData.getFirstBubbleComponentWithDisplay() else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let bubbleHeight: CGFloat
|
||||
|
||||
let lastEventId = lastBubbleComponent.event.eventId
|
||||
let lastMessageBottomPosition = cell.bottomPosition(ofEvent: lastEventId)
|
||||
|
||||
let firstEventId = firstComponent.event.eventId
|
||||
let firstMessageTopPosition = cell.topPosition(ofEvent: firstEventId)
|
||||
|
||||
let additionalContentHeight = roomBubbleCellData.additionalContentHeight
|
||||
|
||||
bubbleHeight = lastMessageBottomPosition - firstMessageTopPosition - additionalContentHeight
|
||||
|
||||
guard bubbleHeight >= 0 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return bubbleHeight
|
||||
}
|
||||
|
||||
// TODO: Improve text message height calculation
|
||||
// This method is closer to final result but lack of stability because of extra vertical space not handled here.
|
||||
// private func getTextMessageHeight(for cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) -> CGFloat? {
|
||||
//
|
||||
// guard let roomBubbleCellData = cellData as? RoomBubbleCellData,
|
||||
// let firstComponent = roomBubbleCellData.getFirstBubbleComponentWithDisplay() else {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// let bubbleHeight: CGFloat
|
||||
//
|
||||
// let componentIndex = cellData.bubbleComponentIndex(forEventId: firstComponent.event.eventId)
|
||||
//
|
||||
// let componentFrame = cell.componentFrameInContentView(for: componentIndex)
|
||||
//
|
||||
// bubbleHeight = componentFrame.height
|
||||
//
|
||||
// guard bubbleHeight >= 0 else {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// return bubbleHeight
|
||||
// }
|
||||
|
||||
private func getMessageBubbleBackgroundHeight(for cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) -> CGFloat? {
|
||||
|
||||
var finalBubbleHeight: CGFloat?
|
||||
let extraMargin: CGFloat = 4.0
|
||||
|
||||
if let bubbleHeight = self.getTextMessageHeight(for: cell, andCellData: cellData) {
|
||||
finalBubbleHeight = bubbleHeight + extraMargin
|
||||
|
||||
} else if let messageTextViewHeight = cell.messageTextView?.frame.height {
|
||||
|
||||
finalBubbleHeight = messageTextViewHeight + extraMargin
|
||||
}
|
||||
|
||||
return finalBubbleHeight
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
private func updateMessageBubbleBackgroundView(_ roomMessageBubbleBackgroundView: RoomMessageBubbleBackgroundView, withCell cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData) -> Bool {
|
||||
|
||||
if let bubbleHeight = self.getMessageBubbleBackgroundHeight(for: cell, andCellData: cellData) {
|
||||
return roomMessageBubbleBackgroundView.updateHeight(bubbleHeight)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private func getIncomingMessageTextViewInsets(from bubbleCell: MXKRoomBubbleTableViewCell) -> UIEdgeInsets {
|
||||
|
||||
let messageViewMarginTop: CGFloat
|
||||
let messageViewMarginBottom: CGFloat = -2.0
|
||||
let messageViewMarginLeft: CGFloat = 3.0
|
||||
let messageViewMarginRight: CGFloat = 80
|
||||
|
||||
if bubbleCell.userNameLabel != nil {
|
||||
messageViewMarginTop = 10.0
|
||||
} else {
|
||||
messageViewMarginTop = 0.0
|
||||
}
|
||||
|
||||
let messageViewInsets = UIEdgeInsets(top: messageViewMarginTop, left: messageViewMarginLeft, bottom: messageViewMarginBottom, right: messageViewMarginRight)
|
||||
|
||||
return messageViewInsets
|
||||
}
|
||||
|
||||
// MARK: Text message
|
||||
|
||||
private func setupIncomingMessageTextViewMargins(for cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
guard cell.messageTextView != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
let messageViewInsets = self.getIncomingMessageTextViewInsets(from: cell)
|
||||
|
||||
cell.msgTextViewBottomConstraint.constant += messageViewInsets.bottom
|
||||
cell.msgTextViewTopConstraint.constant += messageViewInsets.top
|
||||
cell.msgTextViewLeadingConstraint.constant += messageViewInsets.left
|
||||
cell.msgTextViewTrailingConstraint.constant += messageViewInsets.right
|
||||
}
|
||||
|
||||
private func setupOutgoingMessageTextViewMargins(for cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
guard let messageTextView = cell.messageTextView else {
|
||||
return
|
||||
}
|
||||
|
||||
let contentView = cell.contentView
|
||||
|
||||
let leftMargin: CGFloat = 80.0
|
||||
let rightMargin: CGFloat = 78.0
|
||||
let bottomMargin: CGFloat = -2.0
|
||||
|
||||
cell.msgTextViewLeadingConstraint.isActive = false
|
||||
cell.msgTextViewTrailingConstraint.isActive = false
|
||||
|
||||
let leftConstraint = messageTextView.leadingAnchor.constraint(greaterThanOrEqualTo: contentView.leadingAnchor, constant: leftMargin)
|
||||
|
||||
let rightConstraint = messageTextView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -rightMargin)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
leftConstraint,
|
||||
rightConstraint
|
||||
])
|
||||
|
||||
cell.msgTextViewLeadingConstraint = leftConstraint
|
||||
cell.msgTextViewTrailingConstraint = rightConstraint
|
||||
|
||||
cell.msgTextViewBottomConstraint.constant += bottomMargin
|
||||
}
|
||||
|
||||
private func setupOutgoingFileAttachViewMargins(for cell: MXKRoomBubbleTableViewCell) {
|
||||
|
||||
guard let attachmentView = cell.attachmentView else {
|
||||
return
|
||||
}
|
||||
|
||||
let contentView = cell.contentView
|
||||
|
||||
// TODO: Use constants
|
||||
// Same as URL preview
|
||||
let rightMargin: CGFloat = 34.0
|
||||
|
||||
if let attachViewLeadingConstraint = cell.attachViewLeadingConstraint {
|
||||
attachViewLeadingConstraint.isActive = false
|
||||
cell.attachViewLeadingConstraint = nil
|
||||
}
|
||||
|
||||
let rightConstraint = attachmentView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -rightMargin)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
rightConstraint
|
||||
])
|
||||
}
|
||||
}
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator {
|
||||
|
||||
override func addTimestampLabelIfNeeded(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
|
||||
guard self.canShowTimestamp(forCellData: cellData) else {
|
||||
return
|
||||
}
|
||||
|
||||
self.addTimestampLabel(toCell: cell, cellData: cellData)
|
||||
}
|
||||
|
||||
override func addTimestampLabel(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
|
||||
// If cell contains a bubble background, add the timestamp inside of it
|
||||
if let bubbleBackgroundView = cell.messageBubbleBackgroundView, bubbleBackgroundView.isHidden == false {
|
||||
|
||||
let componentIndex = cellData.mostRecentComponentIndex
|
||||
|
||||
guard let bubbleComponents = cellData.bubbleComponents,
|
||||
componentIndex < bubbleComponents.count else {
|
||||
return
|
||||
}
|
||||
|
||||
let component = bubbleComponents[componentIndex]
|
||||
|
||||
let timestampLabel = self.createTimestampLabel(cellData: cellData,
|
||||
bubbleComponent: component,
|
||||
viewTag: componentIndex)
|
||||
timestampLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
cell.addTemporarySubview(timestampLabel)
|
||||
|
||||
bubbleBackgroundView.addSubview(timestampLabel)
|
||||
|
||||
let rightMargin: CGFloat = 8.0
|
||||
let bottomMargin: CGFloat = 4.0
|
||||
|
||||
let trailingConstraint = timestampLabel.trailingAnchor.constraint(equalTo: bubbleBackgroundView.trailingAnchor, constant: -rightMargin)
|
||||
|
||||
let bottomConstraint = timestampLabel.bottomAnchor.constraint(equalTo: bubbleBackgroundView.bottomAnchor, constant: -bottomMargin)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
trailingConstraint,
|
||||
bottomConstraint
|
||||
])
|
||||
} else {
|
||||
super.addTimestampLabel(toCell: cell, cellData: cellData)
|
||||
}
|
||||
}
|
||||
|
||||
override func addReactionView(_ reactionsView: BubbleReactionsView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData, contentViewPositionY: CGFloat, upperDecorationView: UIView?) {
|
||||
|
||||
cell.addTemporarySubview(reactionsView)
|
||||
|
||||
if let reactionsDisplayable = cell as? BubbleCellReactionsDisplayable {
|
||||
reactionsDisplayable.addReactionsView(reactionsView)
|
||||
return
|
||||
}
|
||||
|
||||
reactionsView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let cellContentView = cell.contentView
|
||||
|
||||
cellContentView.addSubview(reactionsView)
|
||||
|
||||
// TODO: Use constants
|
||||
let topMargin: CGFloat = 4.0
|
||||
let leftMargin: CGFloat
|
||||
let rightMargin: CGFloat
|
||||
|
||||
// Outgoing message
|
||||
if cellData.isSenderCurrentUser {
|
||||
reactionsView.alignment = .right
|
||||
|
||||
// TODO: Use constants
|
||||
var outgointLeftMargin: CGFloat = 80.0
|
||||
|
||||
if cellData.containsBubbleComponentWithEncryptionBadge {
|
||||
outgointLeftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin
|
||||
}
|
||||
|
||||
leftMargin = outgointLeftMargin
|
||||
|
||||
// TODO: Use constants
|
||||
rightMargin = 33
|
||||
} else {
|
||||
// Incoming message
|
||||
|
||||
var incomingLeftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin
|
||||
|
||||
if cellData.containsBubbleComponentWithEncryptionBadge {
|
||||
incomingLeftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin
|
||||
}
|
||||
|
||||
leftMargin = incomingLeftMargin - 6.0
|
||||
|
||||
// TODO: Use constants
|
||||
let messageViewMarginRight: CGFloat = 42.0
|
||||
|
||||
rightMargin = messageViewMarginRight
|
||||
}
|
||||
|
||||
let leadingConstraint = reactionsView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin)
|
||||
|
||||
let trailingConstraint = reactionsView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -rightMargin)
|
||||
|
||||
let topConstraint: NSLayoutConstraint
|
||||
if let upperDecorationView = upperDecorationView {
|
||||
topConstraint = reactionsView.topAnchor.constraint(equalTo: upperDecorationView.bottomAnchor, constant: topMargin)
|
||||
} else {
|
||||
topConstraint = reactionsView.topAnchor.constraint(equalTo: cellContentView.topAnchor, constant: contentViewPositionY + topMargin)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
leadingConstraint,
|
||||
trailingConstraint,
|
||||
topConstraint
|
||||
])
|
||||
}
|
||||
|
||||
override func addURLPreviewView(_ urlPreviewView: URLPreviewView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat) {
|
||||
|
||||
cell.addTemporarySubview(urlPreviewView)
|
||||
|
||||
let cellContentView = cell.contentView
|
||||
|
||||
urlPreviewView.translatesAutoresizingMaskIntoConstraints = false
|
||||
urlPreviewView.availableWidth = cellData.maxTextViewWidth
|
||||
cellContentView.addSubview(urlPreviewView)
|
||||
|
||||
let leadingOrTrailingConstraint: NSLayoutConstraint
|
||||
|
||||
// Outgoing message
|
||||
if cellData.isSenderCurrentUser {
|
||||
|
||||
// TODO: Use constants
|
||||
let rightMargin: CGFloat = 34.0
|
||||
|
||||
leadingOrTrailingConstraint = urlPreviewView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -rightMargin)
|
||||
} else {
|
||||
// Incoming message
|
||||
|
||||
var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin
|
||||
if cellData.containsBubbleComponentWithEncryptionBadge {
|
||||
leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin
|
||||
}
|
||||
|
||||
leftMargin-=5.0
|
||||
|
||||
leadingOrTrailingConstraint = urlPreviewView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin)
|
||||
}
|
||||
|
||||
let topMargin = contentViewPositionY + RoomBubbleCellLayout.urlPreviewViewTopMargin + RoomBubbleCellLayout.reactionsViewTopMargin
|
||||
|
||||
// Set the preview view's origin
|
||||
NSLayoutConstraint.activate([
|
||||
leadingOrTrailingConstraint,
|
||||
urlPreviewView.topAnchor.constraint(equalTo: cellContentView.topAnchor, constant: topMargin)
|
||||
])
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func createTimestampLabel(cellData: MXKRoomBubbleCellData, bubbleComponent: MXKRoomBubbleComponent, viewTag: Int) -> UILabel {
|
||||
|
||||
let timeLabel = UILabel()
|
||||
|
||||
timeLabel.text = cellData.eventFormatter.timeString(from: bubbleComponent.date)
|
||||
timeLabel.textAlignment = .right
|
||||
timeLabel.textColor = ThemeService.shared().theme.textSecondaryColor
|
||||
timeLabel.font = UIFont.systemFont(ofSize: 11, weight: .light)
|
||||
timeLabel.adjustsFontSizeToFitWidth = true
|
||||
timeLabel.tag = viewTag
|
||||
timeLabel.accessibilityIdentifier = "timestampLabel"
|
||||
|
||||
return timeLabel
|
||||
}
|
||||
|
||||
private func canShowTimestamp(forCellData cellData: MXKRoomBubbleCellData) -> Bool {
|
||||
|
||||
guard cellData.isCollapsableAndCollapsed == false else {
|
||||
return false
|
||||
}
|
||||
|
||||
guard let firstComponent = cellData.getFirstBubbleComponentWithDisplay(), let firstEvent = firstComponent.event else {
|
||||
return false
|
||||
}
|
||||
|
||||
switch firstEvent.eventType {
|
||||
case .roomMessage:
|
||||
if let messageTypeString = firstEvent.content["msgtype"] as? String {
|
||||
|
||||
let messageType = MXMessageType(identifier: messageTypeString)
|
||||
|
||||
switch messageType {
|
||||
case .text, .emote, .file:
|
||||
return true
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -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 "PlainRoomTimelineCellProvider.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface BubbleRoomTimelineCellProvider : PlainRoomTimelineCellProvider
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// 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 "BubbleRoomTimelineCellProvider.h"
|
||||
|
||||
#pragma mark - Imports
|
||||
|
||||
#pragma mark Text message
|
||||
|
||||
// Outgoing
|
||||
|
||||
// Clear
|
||||
#import "RoomOutgoingTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
|
||||
// Encrypted
|
||||
|
||||
#import "RoomOutgoingEncryptedTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
|
||||
#pragma mark Attachment
|
||||
|
||||
// Outgoing
|
||||
|
||||
// Clear
|
||||
#import "RoomOutgoingAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
// Encrypted
|
||||
#import "RoomOutgoingEncryptedAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
@implementation BubbleRoomTimelineCellProvider
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingTextMessageCellsMapping
|
||||
{
|
||||
// Hide sender info and avatar for bubble outgoing messages
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessage) : RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderInfo) : RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitle) : RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderName) : RoomOutgoingTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitleWithoutSenderName) : RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncrypted) : RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderInfo) : RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitle) : RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderName) : RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitleWithoutSenderName) : RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingAttachmentCellsMapping
|
||||
{
|
||||
// Hide sender info and avatar for bubble outgoing file attachment
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachment) : RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentWithoutSenderInfo) : RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentWithPaginationTitle) : RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncrypted) : RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithoutSenderInfo) : RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithPaginationTitle) : RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.class
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
class BubbleRoomTimelineStyle: RoomTimelineStyle {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var theme: Theme
|
||||
|
||||
// MARK: Public
|
||||
|
||||
let identifier: RoomTimelineStyleIdentifier
|
||||
|
||||
let cellLayoutUpdater: RoomCellLayoutUpdating?
|
||||
|
||||
let cellProvider: RoomTimelineCellProvider
|
||||
|
||||
let cellDecorator: RoomTimelineCellDecorator
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(theme: Theme) {
|
||||
self.theme = theme
|
||||
self.identifier = .bubble
|
||||
self.cellLayoutUpdater = BubbleRoomCellLayoutUpdater(theme: theme)
|
||||
self.cellProvider = BubbleRoomTimelineCellProvider()
|
||||
self.cellDecorator = BubbleRoomTimelineCellDecorator()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func canAddEvent(_ event: MXEvent, and roomState: MXRoomState, to cellData: MXKRoomBubbleCellData) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func applySelectedStyleIfNeeded(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
|
||||
// Check whether the selected event belongs to this bubble
|
||||
let selectedComponentIndex = cellData.selectedComponentIndex
|
||||
if selectedComponentIndex != NSNotFound {
|
||||
|
||||
cell.selectComponent(UInt(selectedComponentIndex),
|
||||
showEditButton: false,
|
||||
showTimestamp: false)
|
||||
|
||||
self.cellDecorator.addTimestampLabel(toCell: cell, cellData: cellData)
|
||||
} else {
|
||||
cell.blurred = true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Themable
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
self.cellLayoutUpdater?.update(theme: theme)
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
extension MXKRoomBubbleTableViewCell {
|
||||
|
||||
// Enables to get existing bubble background view
|
||||
// This used while there is no dedicated cell classes for bubble style
|
||||
var messageBubbleBackgroundView: RoomMessageBubbleBackgroundView? {
|
||||
|
||||
let foundView = self.contentView.subviews.first { view in
|
||||
return view is RoomMessageBubbleBackgroundView
|
||||
}
|
||||
return foundView as? RoomMessageBubbleBackgroundView
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// 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 RoomMessageBubbleBackgroundView: UIView {
|
||||
|
||||
// MARK: - Constant
|
||||
|
||||
private enum Constants {
|
||||
static let cornerRadius: CGFloat = 12.0
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
private var heightConstraint: NSLayoutConstraint?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
convenience init() {
|
||||
self.init(frame: CGRect.zero)
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.layer.masksToBounds = true
|
||||
self.layer.cornerRadius = Constants.cornerRadius
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
@discardableResult
|
||||
func updateHeight(_ height: CGFloat) -> Bool {
|
||||
if let heightConstraint = self.heightConstraint {
|
||||
|
||||
guard heightConstraint.constant != height else {
|
||||
return false
|
||||
}
|
||||
|
||||
heightConstraint.constant = height
|
||||
|
||||
return true
|
||||
} else {
|
||||
let heightConstraint = self.heightAnchor.constraint(equalToConstant: height)
|
||||
heightConstraint.isActive = true
|
||||
self.heightConstraint = heightConstraint
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
@objcMembers
|
||||
class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator {
|
||||
|
||||
func addTimestampLabelIfNeeded(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
|
||||
guard cellData.containsLastMessage && cellData.isCollapsableAndCollapsed == false else {
|
||||
return
|
||||
}
|
||||
|
||||
// Display timestamp of the last message
|
||||
self.addTimestampLabel(toCell: cell, cellData: cellData)
|
||||
}
|
||||
|
||||
func addTimestampLabel(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
cell.addTimestampLabel(forComponent: UInt(cellData.mostRecentComponentIndex))
|
||||
}
|
||||
|
||||
func addURLPreviewView(_ urlPreviewView: URLPreviewView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat) {
|
||||
cell.addTemporarySubview(urlPreviewView)
|
||||
|
||||
let cellContentView = cell.contentView
|
||||
|
||||
urlPreviewView.translatesAutoresizingMaskIntoConstraints = false
|
||||
urlPreviewView.availableWidth = cellData.maxTextViewWidth
|
||||
cellContentView.addSubview(urlPreviewView)
|
||||
|
||||
var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin
|
||||
if cellData.containsBubbleComponentWithEncryptionBadge {
|
||||
leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin
|
||||
}
|
||||
|
||||
let topMargin = contentViewPositionY + RoomBubbleCellLayout.urlPreviewViewTopMargin + RoomBubbleCellLayout.reactionsViewTopMargin
|
||||
|
||||
// Set the preview view's origin
|
||||
NSLayoutConstraint.activate([
|
||||
urlPreviewView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin),
|
||||
urlPreviewView.topAnchor.constraint(equalTo: cellContentView.topAnchor, constant: topMargin)
|
||||
])
|
||||
}
|
||||
|
||||
func addReactionView(_ reactionsView: BubbleReactionsView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat,
|
||||
upperDecorationView: UIView?) {
|
||||
|
||||
cell.addTemporarySubview(reactionsView)
|
||||
|
||||
if let reactionsDisplayable = cell as? BubbleCellReactionsDisplayable {
|
||||
reactionsDisplayable.addReactionsView(reactionsView)
|
||||
} else {
|
||||
reactionsView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let cellContentView = cell.contentView
|
||||
|
||||
cellContentView.addSubview(reactionsView)
|
||||
|
||||
var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin
|
||||
|
||||
if cellData.containsBubbleComponentWithEncryptionBadge {
|
||||
leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin
|
||||
}
|
||||
|
||||
let rightMargin = RoomBubbleCellLayout.reactionsViewRightMargin
|
||||
let topMargin = RoomBubbleCellLayout.reactionsViewTopMargin
|
||||
|
||||
// The top constraint may need to include the URL preview view
|
||||
let topConstraint: NSLayoutConstraint
|
||||
if let upperDecorationView = upperDecorationView {
|
||||
topConstraint = reactionsView.topAnchor.constraint(equalTo: upperDecorationView.bottomAnchor, constant: topMargin)
|
||||
} else {
|
||||
topConstraint = reactionsView.topAnchor.constraint(equalTo: cellContentView.topAnchor, constant: contentViewPositionY + topMargin)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
reactionsView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin),
|
||||
reactionsView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -rightMargin),
|
||||
topConstraint
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
func addReadReceiptsView(_ readReceiptsView: MXKReceiptSendersContainer,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat,
|
||||
upperDecorationView: UIView?) {
|
||||
|
||||
cell.addTemporarySubview(readReceiptsView)
|
||||
|
||||
if let readReceiptsDisplayable = cell as? BubbleCellReadReceiptsDisplayable {
|
||||
readReceiptsDisplayable.addReadReceiptsView(readReceiptsView)
|
||||
} else {
|
||||
|
||||
let cellContentView = cell.contentView
|
||||
|
||||
cellContentView.addSubview(readReceiptsView)
|
||||
|
||||
// Force receipts container size
|
||||
let widthConstraint = readReceiptsView.widthAnchor.constraint(equalToConstant: RoomBubbleCellLayout.readReceiptsViewWidth)
|
||||
let heightConstraint = readReceiptsView.heightAnchor.constraint(equalToConstant: RoomBubbleCellLayout.readReceiptsViewHeight)
|
||||
|
||||
// Force receipts container position
|
||||
let trailingConstraint = readReceiptsView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -RoomBubbleCellLayout.readReceiptsViewRightMargin)
|
||||
|
||||
let topMargin = RoomBubbleCellLayout.readReceiptsViewTopMargin
|
||||
|
||||
let topConstraint: NSLayoutConstraint
|
||||
if let upperDecorationView = upperDecorationView {
|
||||
topConstraint = readReceiptsView.topAnchor.constraint(equalTo: upperDecorationView.bottomAnchor, constant: topMargin)
|
||||
} else {
|
||||
topConstraint = readReceiptsView.topAnchor.constraint(equalTo: cellContentView.topAnchor, constant: contentViewPositionY + topMargin)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
widthConstraint,
|
||||
heightConstraint,
|
||||
trailingConstraint,
|
||||
topConstraint
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat,
|
||||
upperDecorationView: UIView?) {
|
||||
|
||||
cell.addTemporarySubview(threadSummaryView)
|
||||
|
||||
if let threadSummaryDisplayable = cell as? BubbleCellThreadSummaryDisplayable {
|
||||
threadSummaryDisplayable.addThreadSummaryView(threadSummaryView)
|
||||
} else {
|
||||
threadSummaryView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let cellContentView = cell.contentView
|
||||
|
||||
cellContentView.addSubview(threadSummaryView)
|
||||
|
||||
var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin
|
||||
|
||||
if cellData.containsBubbleComponentWithEncryptionBadge {
|
||||
leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin
|
||||
}
|
||||
|
||||
let rightMargin = RoomBubbleCellLayout.reactionsViewRightMargin
|
||||
let topMargin = RoomBubbleCellLayout.threadSummaryViewTopMargin
|
||||
let height = ThreadSummaryView.contentViewHeight(forThread: threadSummaryView.thread,
|
||||
fitting: cellData.maxTextViewWidth)
|
||||
|
||||
// The top constraint may need to include the URL preview view
|
||||
let topConstraint: NSLayoutConstraint
|
||||
if let upperDecorationView = upperDecorationView {
|
||||
topConstraint = threadSummaryView.topAnchor.constraint(equalTo: upperDecorationView.bottomAnchor,
|
||||
constant: topMargin)
|
||||
} else {
|
||||
topConstraint = threadSummaryView.topAnchor.constraint(equalTo: cellContentView.topAnchor,
|
||||
constant: contentViewPositionY + topMargin)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
threadSummaryView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor,
|
||||
constant: leftMargin),
|
||||
threadSummaryView.trailingAnchor.constraint(lessThanOrEqualTo: cellContentView.trailingAnchor,
|
||||
constant: -rightMargin),
|
||||
threadSummaryView.heightAnchor.constraint(equalToConstant: height),
|
||||
topConstraint
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
func addSendStatusView(toCell cell: MXKRoomBubbleTableViewCell, withFailedEventIds failedEventIds: Set<AnyHashable>) {
|
||||
cell.updateTickView(withFailedEventIds: failedEventIds)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// 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 "RoomTimelineCellProvider.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface PlainRoomTimelineCellProvider: NSObject<RoomTimelineCellProvider>
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingTextMessageCellsMapping;
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingAttachmentCellsMapping;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,453 @@
|
||||
//
|
||||
// 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 "PlainRoomTimelineCellProvider.h"
|
||||
|
||||
#import "MXKRoomBubbleTableViewCell+Riot.h"
|
||||
|
||||
#import "RoomEmptyBubbleCell.h"
|
||||
|
||||
#import "RoomIncomingTextMsgBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomIncomingEncryptedTextMsgBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomOutgoingTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
|
||||
#import "RoomOutgoingEncryptedTextMsgBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h"
|
||||
#import "RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h"
|
||||
|
||||
#import "RoomMembershipBubbleCell.h"
|
||||
#import "RoomMembershipWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomMembershipCollapsedBubbleCell.h"
|
||||
#import "RoomMembershipCollapsedWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomMembershipExpandedBubbleCell.h"
|
||||
#import "RoomMembershipExpandedWithPaginationTitleBubbleCell.h"
|
||||
#import "RoomCreationWithPaginationCollapsedBubbleCell.h"
|
||||
#import "RoomCreationCollapsedBubbleCell.h"
|
||||
|
||||
#import "RoomSelectedStickerBubbleCell.h"
|
||||
#import "RoomPredecessorBubbleCell.h"
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@interface PlainRoomTimelineCellProvider()
|
||||
|
||||
@property (nonatomic, strong) NSDictionary<NSNumber*, Class>* cellClasses;
|
||||
|
||||
@end
|
||||
|
||||
@implementation PlainRoomTimelineCellProvider
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (void)registerCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
// Text message
|
||||
|
||||
[self registerIncomingTextMessageCellsForTableView:tableView];
|
||||
|
||||
[self registerOutgoingTextMessageCellsForTableView:tableView];
|
||||
|
||||
// Attachment cells
|
||||
|
||||
[self registerIncomingAttachmentCellsForTableView:tableView];
|
||||
|
||||
[self registerOutgoingAttachmentCellsForTableView:tableView];
|
||||
|
||||
// Other cells
|
||||
|
||||
[self registerMembershipCellsForTableView:tableView];
|
||||
|
||||
[self registerKeyVerificationCellsForTableView:tableView];
|
||||
|
||||
[self registerRoomCreationCellsForTableView:tableView];
|
||||
|
||||
[self registerCallCellsForTableView:tableView];
|
||||
|
||||
[self registerVoiceMessageCellsForTableView:tableView];
|
||||
|
||||
[self registerPollCellsForTableView:tableView];
|
||||
|
||||
[self registerLocationCellsForTableView:tableView];
|
||||
|
||||
[tableView registerClass:RoomEmptyBubbleCell.class forCellReuseIdentifier:RoomEmptyBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[tableView registerClass:RoomSelectedStickerBubbleCell.class forCellReuseIdentifier:RoomSelectedStickerBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[tableView registerClass:RoomPredecessorBubbleCell.class forCellReuseIdentifier:RoomPredecessorBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
[tableView registerClass:RoomCreationIntroCell.class forCellReuseIdentifier:RoomCreationIntroCell.defaultReuseIdentifier];
|
||||
|
||||
[tableView registerNib:RoomTypingBubbleCell.nib forCellReuseIdentifier:RoomTypingBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (Class<MXKCellRendering>)cellViewClassForCellIdentifier:(RoomTimelineCellIdentifier)identifier
|
||||
{
|
||||
if (self.cellClasses == nil)
|
||||
{
|
||||
self.cellClasses = [self buildCellClasses];
|
||||
}
|
||||
|
||||
Class cellViewClass = self.cellClasses[@(identifier)];
|
||||
|
||||
|
||||
return cellViewClass;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
#pragma mark Cell registration
|
||||
|
||||
- (void)registerIncomingTextMessageCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
// Clear
|
||||
|
||||
[tableView registerClass:RoomIncomingTextMsgBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
// Encrypted
|
||||
|
||||
[tableView registerClass:RoomIncomingEncryptedTextMsgBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerOutgoingTextMessageCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
// Clear
|
||||
|
||||
[tableView registerClass:RoomOutgoingTextMsgBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
// Encrypted
|
||||
|
||||
[tableView registerClass:RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedTextMsgBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerIncomingAttachmentCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
// Clear
|
||||
|
||||
[tableView registerClass:RoomIncomingAttachmentBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
// Encrypted
|
||||
|
||||
[tableView registerClass:RoomIncomingEncryptedAttachmentBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerOutgoingAttachmentCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
// Clear
|
||||
|
||||
[tableView registerClass:RoomOutgoingAttachmentBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingAttachmentWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.class forCellReuseIdentifier:RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.defaultReuseIdentifier];
|
||||
|
||||
// Encrypted
|
||||
|
||||
[tableView registerClass:RoomOutgoingEncryptedAttachmentBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerMembershipCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:RoomMembershipBubbleCell.class forCellReuseIdentifier:RoomMembershipBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomMembershipWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomMembershipCollapsedBubbleCell.class forCellReuseIdentifier:RoomMembershipCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomMembershipCollapsedWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipCollapsedWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomMembershipExpandedBubbleCell.class forCellReuseIdentifier:RoomMembershipExpandedBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomMembershipExpandedWithPaginationTitleBubbleCell.class forCellReuseIdentifier:RoomMembershipExpandedWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerKeyVerificationCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:KeyVerificationIncomingRequestApprovalBubbleCell.class forCellReuseIdentifier:KeyVerificationIncomingRequestApprovalBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:KeyVerificationRequestStatusBubbleCell.class forCellReuseIdentifier:KeyVerificationRequestStatusBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:KeyVerificationRequestStatusWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationRequestStatusWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:KeyVerificationConclusionBubbleCell.class forCellReuseIdentifier:KeyVerificationConclusionBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:KeyVerificationConclusionWithPaginationTitleBubbleCell.class forCellReuseIdentifier:KeyVerificationConclusionWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerRoomCreationCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:RoomCreationCollapsedBubbleCell.class forCellReuseIdentifier:RoomCreationCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomCreationWithPaginationCollapsedBubbleCell.class forCellReuseIdentifier:RoomCreationWithPaginationCollapsedBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerCallCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:RoomDirectCallStatusBubbleCell.class forCellReuseIdentifier:RoomDirectCallStatusBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:RoomGroupCallStatusBubbleCell.class forCellReuseIdentifier:RoomGroupCallStatusBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerVoiceMessageCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:VoiceMessageBubbleCell.class forCellReuseIdentifier:VoiceMessageBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:VoiceMessageWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:VoiceMessageWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:VoiceMessageWithPaginationTitleBubbleCell.class forCellReuseIdentifier:VoiceMessageWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerPollCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:PollBubbleCell.class forCellReuseIdentifier:PollBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:PollWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:PollWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:PollWithPaginationTitleBubbleCell.class forCellReuseIdentifier:PollWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
- (void)registerLocationCellsForTableView:(UITableView*)tableView
|
||||
{
|
||||
[tableView registerClass:LocationBubbleCell.class forCellReuseIdentifier:LocationBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:LocationWithoutSenderInfoBubbleCell.class forCellReuseIdentifier:LocationWithoutSenderInfoBubbleCell.defaultReuseIdentifier];
|
||||
[tableView registerClass:LocationWithPaginationTitleBubbleCell.class forCellReuseIdentifier:LocationWithPaginationTitleBubbleCell.defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
#pragma mark Cell class association
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)buildCellClasses
|
||||
{
|
||||
NSMutableDictionary<NSNumber*, Class>* cellClasses = [NSMutableDictionary dictionary];
|
||||
|
||||
// Text message
|
||||
|
||||
NSDictionary *incomingTextMessageCellsMapping = [self incomingTextMessageCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:incomingTextMessageCellsMapping];
|
||||
|
||||
NSDictionary *outgoingTextMessageCellsMapping = [self outgoingTextMessageCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:outgoingTextMessageCellsMapping];
|
||||
|
||||
// Attachment
|
||||
|
||||
NSDictionary *incomingAttachmentCellsMapping = [self incomingAttachmentCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:incomingAttachmentCellsMapping];
|
||||
|
||||
NSDictionary *outgoingAttachmentCellsMapping = [self outgoingAttachmentCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:outgoingAttachmentCellsMapping];
|
||||
|
||||
// Other cells
|
||||
|
||||
NSDictionary *roomMembershipCellsMapping = [self membershipCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:roomMembershipCellsMapping];
|
||||
|
||||
NSDictionary *keyVerificationCellsMapping = [self keyVerificationCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:keyVerificationCellsMapping];
|
||||
|
||||
NSDictionary *roomCreationCellsMapping = [self roomCreationCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:roomCreationCellsMapping];
|
||||
|
||||
NSDictionary *callCellsMapping = [self callCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:callCellsMapping];
|
||||
|
||||
NSDictionary *voiceMessageCellsMapping = [self voiceMessageCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:voiceMessageCellsMapping];
|
||||
|
||||
NSDictionary *pollCellsMapping = [self pollCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:pollCellsMapping];
|
||||
|
||||
NSDictionary *locationCellsMapping = [self locationCellsMapping];
|
||||
[cellClasses addEntriesFromDictionary:locationCellsMapping];
|
||||
|
||||
NSDictionary *othersCells = @{
|
||||
@(RoomTimelineCellIdentifierEmpty) : RoomEmptyBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierSelectedSticker) : RoomSelectedStickerBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierRoomPredecessor) : RoomPredecessorBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierRoomCreationIntro) : RoomCreationIntroCell.class,
|
||||
@(RoomTimelineCellIdentifierTyping) : RoomTypingBubbleCell.class,
|
||||
};
|
||||
[cellClasses addEntriesFromDictionary:othersCells];
|
||||
|
||||
return [cellClasses copy];
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)incomingTextMessageCellsMapping
|
||||
{
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessage) : RoomIncomingTextMsgBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderInfo) : RoomIncomingTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitle) : RoomIncomingTextMsgWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageWithoutSenderName) : RoomIncomingTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageWithPaginationTitleWithoutSenderName) : RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageEncrypted) : RoomIncomingEncryptedTextMsgBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderInfo) : RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitle) : RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithoutSenderName) : RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingTextMessageEncryptedWithPaginationTitleWithoutSenderName) : RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingTextMessageCellsMapping
|
||||
{
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessage) : RoomOutgoingTextMsgBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderInfo) : RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitle) : RoomOutgoingTextMsgWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithoutSenderName) : RoomOutgoingTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageWithPaginationTitleWithoutSenderName) : RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncrypted) : RoomOutgoingEncryptedTextMsgBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderInfo) : RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitle) : RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithoutSenderName) : RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingTextMessageEncryptedWithPaginationTitleWithoutSenderName) : RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)incomingAttachmentCellsMapping
|
||||
{
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierIncomingAttachment) : RoomIncomingAttachmentBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingAttachmentWithoutSenderInfo) : RoomIncomingAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingAttachmentWithPaginationTitle) : RoomIncomingAttachmentWithPaginationTitleBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierIncomingAttachmentEncrypted) : RoomIncomingEncryptedAttachmentBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithoutSenderInfo) : RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierIncomingAttachmentEncryptedWithPaginationTitle) : RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.class
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)outgoingAttachmentCellsMapping
|
||||
{
|
||||
return @{
|
||||
// Clear
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachment) : RoomOutgoingAttachmentBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentWithoutSenderInfo) : RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentWithPaginationTitle) : RoomOutgoingAttachmentWithPaginationTitleBubbleCell.class,
|
||||
// Encrypted
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncrypted) : RoomOutgoingEncryptedAttachmentBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithoutSenderInfo) : RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierOutgoingAttachmentEncryptedWithPaginationTitle) : RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.class
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)membershipCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierMembership) : RoomMembershipBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierMembershipWithPaginationTitle) : RoomMembershipWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierMembershipCollapsed) : RoomMembershipCollapsedBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierMembershipCollapsedWithPaginationTitle) : RoomMembershipCollapsedWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierMembershipExpanded) : RoomMembershipExpandedBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierMembershipExpandedWithPaginationTitle) : RoomMembershipExpandedWithPaginationTitleBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)keyVerificationCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierKeyVerificationIncomingRequestApproval) : KeyVerificationIncomingRequestApprovalBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierKeyVerificationIncomingRequestApprovalWithPaginationTitle) : KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierKeyVerificationRequestStatus) : KeyVerificationRequestStatusBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierKeyVerificationRequestStatusWithPaginationTitle) : KeyVerificationRequestStatusWithPaginationTitleBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierKeyVerificationConclusion) : KeyVerificationConclusionBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierKeyVerificationConclusionWithPaginationTitle) : KeyVerificationConclusionWithPaginationTitleBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)roomCreationCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierRoomCreationCollapsed) : RoomCreationCollapsedBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierRoomCreationCollapsedWithPaginationTitle) : RoomCreationWithPaginationCollapsedBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)callCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierDirectCallStatus) : RoomDirectCallStatusBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierGroupCallStatus) : RoomGroupCallStatusBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)voiceMessageCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierVoiceMessage) : VoiceMessageBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierVoiceMessageWithoutSenderInfo) : VoiceMessageWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierVoiceMessageWithPaginationTitle) : VoiceMessageWithPaginationTitleBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)pollCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierPoll) : PollBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierPollWithoutSenderInfo) : PollWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierPollWithPaginationTitle) : PollWithPaginationTitleBubbleCell.class,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary<NSNumber*, Class>*)locationCellsMapping
|
||||
{
|
||||
return @{
|
||||
@(RoomTimelineCellIdentifierLocation) : LocationBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierLocationWithoutSenderInfo) : LocationWithoutSenderInfoBubbleCell.class,
|
||||
@(RoomTimelineCellIdentifierLocationWithPaginationTitle) : LocationWithPaginationTitleBubbleCell.class
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// 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 PlainRoomTimelineStyle: RoomTimelineStyle {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var theme: Theme
|
||||
|
||||
// MARK: Public
|
||||
|
||||
let identifier: RoomTimelineStyleIdentifier
|
||||
|
||||
let cellLayoutUpdater: RoomCellLayoutUpdating?
|
||||
|
||||
let cellProvider: RoomTimelineCellProvider
|
||||
|
||||
let cellDecorator: RoomTimelineCellDecorator
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(theme: Theme) {
|
||||
self.theme = theme
|
||||
self.identifier = .plain
|
||||
self.cellLayoutUpdater = nil
|
||||
self.cellProvider = PlainRoomTimelineCellProvider()
|
||||
self.cellDecorator = PlainRoomTimelineCellDecorator()
|
||||
}
|
||||
|
||||
// MARK: - Methods
|
||||
|
||||
func canAddEvent(_ event: MXEvent, and roomState: MXRoomState, to cellData: MXKRoomBubbleCellData) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func applySelectedStyleIfNeeded(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData) {
|
||||
|
||||
// Check whether the selected event belongs to this bubble
|
||||
let selectedComponentIndex = cellData.selectedComponentIndex
|
||||
if selectedComponentIndex != NSNotFound {
|
||||
|
||||
let showTimestamp = cellData.showTimestampForSelectedComponent
|
||||
|
||||
cell.selectComponent(UInt(selectedComponentIndex),
|
||||
showEditButton: false,
|
||||
showTimestamp: showTimestamp)
|
||||
} else {
|
||||
cell.blurred = true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Themable
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
/// Enables to setup or update a room timeline cell view
|
||||
@objc
|
||||
protocol RoomCellLayoutUpdating: Themable {
|
||||
|
||||
func updateLayoutIfNeeded(for cell: MXKRoomBubbleTableViewCell, andCellData cellData: MXKRoomBubbleCellData)
|
||||
|
||||
func setupLayout(forIncomingTextMessageCell cell: MXKRoomBubbleTableViewCell)
|
||||
|
||||
func setupLayout(forOutgoingTextMessageCell cell: MXKRoomBubbleTableViewCell)
|
||||
|
||||
func setupLayout(forOutgoingFileAttachmentCell cell: MXKRoomBubbleTableViewCell)
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
/// RoomTimelineCellDecorator enables to add decoration on a cell (reactions, read receipts, timestamp, URL preview).
|
||||
@objc
|
||||
protocol RoomTimelineCellDecorator {
|
||||
|
||||
func addTimestampLabelIfNeeded(toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData)
|
||||
|
||||
func addTimestampLabel(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData)
|
||||
|
||||
func addURLPreviewView(_ urlPreviewView: URLPreviewView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat)
|
||||
|
||||
func addReactionView(_ reactionsView: BubbleReactionsView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat,
|
||||
upperDecorationView: UIView?)
|
||||
|
||||
func addReadReceiptsView(_ readReceiptsView: MXKReceiptSendersContainer,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat,
|
||||
upperDecorationView: UIView?)
|
||||
|
||||
func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView,
|
||||
toCell cell: MXKRoomBubbleTableViewCell,
|
||||
cellData: RoomBubbleCellData,
|
||||
contentViewPositionY: CGFloat,
|
||||
upperDecorationView: UIView?)
|
||||
|
||||
func addSendStatusView(toCell cell: MXKRoomBubbleTableViewCell,
|
||||
withFailedEventIds failedEventIds: Set<AnyHashable>)
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// 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/UIKit.h>
|
||||
|
||||
#import "RoomTimelineCellIdentifier.h"
|
||||
#import "MXKCellRendering.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Enables to register and provide room timeline cells
|
||||
@protocol RoomTimelineCellProvider <NSObject>
|
||||
|
||||
/// Register timeline cells for the given table view
|
||||
- (void)registerCellsForTableView:(UITableView*)tableView;
|
||||
|
||||
/// Get timeline cell class from cell identifier
|
||||
- (Class<MXKCellRendering>)cellViewClassForCellIdentifier:(RoomTimelineCellIdentifier)identifier;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// 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
|
||||
import MatrixSDK
|
||||
|
||||
/// RoomTimelineStyle describes a room timeline style used to customize timeline appearance
|
||||
@objc
|
||||
protocol RoomTimelineStyle: Themable {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// Style identifier
|
||||
var identifier: RoomTimelineStyleIdentifier { get }
|
||||
|
||||
/// Update layout if needed for cells provided by the cell provider
|
||||
var cellLayoutUpdater: RoomCellLayoutUpdating? { get }
|
||||
|
||||
/// Register and provide timeline cells
|
||||
var cellProvider: RoomTimelineCellProvider { get }
|
||||
|
||||
/// Handle cell decorations (reactions, read receipts, URL preview, …)
|
||||
var cellDecorator: RoomTimelineCellDecorator { get }
|
||||
|
||||
// MARK: - Methods
|
||||
|
||||
/// Indicate to merge or not event in timeline
|
||||
func canAddEvent(_ event: MXEvent, and roomState: MXRoomState, to cellData: MXKRoomBubbleCellData) -> Bool
|
||||
|
||||
/// Apply selected or blurred style on cell
|
||||
func applySelectedStyleIfNeeded(toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData)
|
||||
}
|
||||
@@ -17,7 +17,8 @@
|
||||
import Foundation
|
||||
|
||||
/// Represents the room timeline style identifiers available
|
||||
enum RoomTimelineStyleIdentifier {
|
||||
@objc
|
||||
enum RoomTimelineStyleIdentifier: Int {
|
||||
case plain
|
||||
case bubble
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomIncomingBubbleTableViewCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomIncomingTextMsgBubbleCell` displays incoming message bubbles with sender's information.
|
||||
*/
|
||||
@interface MXKRoomIncomingTextMsgBubbleCell : MXKRoomIncomingBubbleTableViewCell
|
||||
|
||||
@end
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomIncomingTextMsgBubbleCell.h"
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@implementation MXKRoomIncomingTextMsgBubbleCell
|
||||
|
||||
- (void)setupViews
|
||||
{
|
||||
[super setupViews];
|
||||
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
[timelineConfiguration.currentStyle.cellLayoutUpdater setupLayoutForIncomingTextMessageCell:self];
|
||||
}
|
||||
|
||||
@end
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="WmY-Jw-mqv" customClass="MXKRoomIncomingTextMsgBubbleCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="49.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="hgp-Z5-rAj" userLabel="Picture View" customClass="MXKImageView">
|
||||
<rect key="frame" x="8" y="5" width="40" height="40"/>
|
||||
<color key="backgroundColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="40" id="NQk-ck-Lo8"/>
|
||||
<constraint firstAttribute="height" constant="40" id="dNT-QU-CUG"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="zwq-eh-8Fb" userLabel="typingBadge">
|
||||
<rect key="frame" x="5" y="0.0" width="20" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="20" id="7ni-rb-ovL"/>
|
||||
<constraint firstAttribute="height" constant="20" id="mcu-rQ-hnj"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="User name:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="8" translatesAutoresizingMaskIntoConstraints="NO" id="q9c-0p-QyP">
|
||||
<rect key="frame" x="51" y="3" width="480" height="20"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" placeholder="YES" id="5ZO-W1-tS2"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="13"/>
|
||||
<color key="textColor" red="0.33333333333333331" green="0.33333333333333331" blue="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" text="text message" translatesAutoresizingMaskIntoConstraints="NO" id="HTH-5n-MSU" customClass="MXKMessageTextView">
|
||||
<rect key="frame" x="51" y="10" width="97" height="39.5"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="97" id="9EQ-AP-La0"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="39" id="ZZt-rc-tVJ"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
||||
</textView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kwd-hP-feC" userLabel="showHideDateTime">
|
||||
<rect key="frame" x="531" y="0.0" width="69" height="49.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="69" id="9vA-4g-EE5"/>
|
||||
</constraints>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="showHideDateTime:" destination="WmY-Jw-mqv" eventType="touchUpInside" id="jYV-nj-p60"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW" userLabel="bubbleInfoContainer">
|
||||
<rect key="frame" x="531" y="10" width="61" height="39.5"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="61" id="tLr-6k-ArA"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L3N-gy-H1n">
|
||||
<rect key="frame" x="48" y="0.0" width="486" height="26"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="hgp-Z5-rAj" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="5" id="2Ih-ga-N9s"/>
|
||||
<constraint firstItem="kwd-hP-feC" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" id="5bB-HV-WAA"/>
|
||||
<constraint firstItem="L3N-gy-H1n" firstAttribute="leading" secondItem="q9c-0p-QyP" secondAttribute="leading" constant="-3" id="7gc-A2-DNj"/>
|
||||
<constraint firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" constant="69" id="Bkh-h2-JOQ"/>
|
||||
<constraint firstItem="L3N-gy-H1n" firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" constant="3" id="FLX-Dd-CqO"/>
|
||||
<constraint firstItem="L3N-gy-H1n" firstAttribute="bottom" secondItem="q9c-0p-QyP" secondAttribute="bottom" constant="3" id="IpR-cp-Yod"/>
|
||||
<constraint firstItem="q9c-0p-QyP" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="3" id="Ixr-7h-f8j"/>
|
||||
<constraint firstAttribute="bottom" secondItem="kwd-hP-feC" secondAttribute="bottom" id="LQg-cI-Nkn"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="HTH-5n-MSU" secondAttribute="trailing" constant="69" id="Shz-6S-kGd"/>
|
||||
<constraint firstAttribute="bottom" secondItem="IOg-Kt-8vW" secondAttribute="bottom" id="TPw-iE-nii"/>
|
||||
<constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="XSL-TG-m62"/>
|
||||
<constraint firstItem="q9c-0p-QyP" firstAttribute="leading" secondItem="hgp-Z5-rAj" secondAttribute="trailing" constant="3" id="YWK-C2-15w"/>
|
||||
<constraint firstItem="zwq-eh-8Fb" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="5" id="dgK-4e-UuE"/>
|
||||
<constraint firstAttribute="trailing" secondItem="kwd-hP-feC" secondAttribute="trailing" id="f2V-Ka-kU3"/>
|
||||
<constraint firstAttribute="trailing" secondItem="IOg-Kt-8vW" secondAttribute="trailing" constant="8" id="hQV-lO-7aQ"/>
|
||||
<constraint firstItem="HTH-5n-MSU" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="mkw-3s-H8B"/>
|
||||
<constraint firstAttribute="bottom" secondItem="HTH-5n-MSU" secondAttribute="bottom" id="oTk-3F-SEC"/>
|
||||
<constraint firstItem="zwq-eh-8Fb" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" id="tUd-UR-lzA"/>
|
||||
<constraint firstItem="L3N-gy-H1n" firstAttribute="top" secondItem="q9c-0p-QyP" secondAttribute="top" constant="-3" id="tXi-p0-wft"/>
|
||||
<constraint firstItem="hgp-Z5-rAj" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="8" id="tuw-aU-ncu"/>
|
||||
<constraint firstItem="HTH-5n-MSU" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="51" id="uig-Xh-7m6"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="bubbleInfoContainer" destination="IOg-Kt-8vW" id="TAw-QY-Y9e"/>
|
||||
<outlet property="bubbleInfoContainerTopConstraint" destination="XSL-TG-m62" id="qVf-vJ-4aP"/>
|
||||
<outlet property="messageTextView" destination="HTH-5n-MSU" id="YN4-iK-gNc"/>
|
||||
<outlet property="msgTextViewBottomConstraint" destination="oTk-3F-SEC" id="o0p-3S-hM4"/>
|
||||
<outlet property="msgTextViewLeadingConstraint" destination="uig-Xh-7m6" id="kgj-3v-ECW"/>
|
||||
<outlet property="msgTextViewMinHeightConstraint" destination="ZZt-rc-tVJ" id="hDD-TL-PFM"/>
|
||||
<outlet property="msgTextViewTopConstraint" destination="mkw-3s-H8B" id="lON-oG-Xx9"/>
|
||||
<outlet property="msgTextViewTrailingConstraint" destination="Shz-6S-kGd" id="5ib-m6-Lna"/>
|
||||
<outlet property="msgTextViewWidthConstraint" destination="9EQ-AP-La0" id="wgi-Yc-sTT"/>
|
||||
<outlet property="pictureView" destination="hgp-Z5-rAj" id="rKM-QG-RJN"/>
|
||||
<outlet property="typingBadge" destination="zwq-eh-8Fb" id="4vs-Dk-vWt"/>
|
||||
<outlet property="userNameLabel" destination="q9c-0p-QyP" id="JId-R7-LoM"/>
|
||||
<outlet property="userNameTapGestureMaskView" destination="L3N-gy-H1n" id="1Eb-Vn-fSP"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomIncomingTextMsgBubbleCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell` displays incoming message bubbles without sender's information.
|
||||
*/
|
||||
@interface MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell : MXKRoomIncomingTextMsgBubbleCell
|
||||
|
||||
@end
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
|
||||
@implementation MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell
|
||||
|
||||
@end
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="WmY-Jw-mqv" customClass="MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="34.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" text="text message" translatesAutoresizingMaskIntoConstraints="NO" id="HTH-5n-MSU" customClass="MXKMessageTextView">
|
||||
<rect key="frame" x="51" y="0.0" width="97" height="34.5"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="29" id="SHB-dF-A5J"/>
|
||||
<constraint firstAttribute="width" constant="97" id="aQ3-Pg-LVD"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
||||
</textView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kwd-hP-feC" userLabel="showHideDateTime">
|
||||
<rect key="frame" x="531" y="0.0" width="69" height="34.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="69" id="9vA-4g-EE5"/>
|
||||
</constraints>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="showHideDateTime:" destination="WmY-Jw-mqv" eventType="touchUpInside" id="jYV-nj-p60"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW" userLabel="bubbleInfoContainer">
|
||||
<rect key="frame" x="531" y="0.0" width="61" height="34.5"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="61" id="tLr-6k-ArA"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="kwd-hP-feC" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" id="5bB-HV-WAA"/>
|
||||
<constraint firstAttribute="bottom" secondItem="kwd-hP-feC" secondAttribute="bottom" id="LQg-cI-Nkn"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="HTH-5n-MSU" secondAttribute="trailing" constant="69" id="Shz-6S-kGd"/>
|
||||
<constraint firstAttribute="bottom" secondItem="IOg-Kt-8vW" secondAttribute="bottom" id="TPw-iE-nii"/>
|
||||
<constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" id="XSL-TG-m62"/>
|
||||
<constraint firstAttribute="trailing" secondItem="kwd-hP-feC" secondAttribute="trailing" id="f2V-Ka-kU3"/>
|
||||
<constraint firstAttribute="trailing" secondItem="IOg-Kt-8vW" secondAttribute="trailing" constant="8" id="hQV-lO-7aQ"/>
|
||||
<constraint firstItem="HTH-5n-MSU" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" id="mkw-3s-H8B"/>
|
||||
<constraint firstAttribute="bottom" secondItem="HTH-5n-MSU" secondAttribute="bottom" id="oTk-3F-SEC"/>
|
||||
<constraint firstItem="HTH-5n-MSU" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="51" id="uig-Xh-7m6"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="bubbleInfoContainer" destination="IOg-Kt-8vW" id="TAw-QY-Y9e"/>
|
||||
<outlet property="bubbleInfoContainerTopConstraint" destination="XSL-TG-m62" id="qVf-vJ-4aP"/>
|
||||
<outlet property="messageTextView" destination="HTH-5n-MSU" id="YN4-iK-gNc"/>
|
||||
<outlet property="msgTextViewBottomConstraint" destination="oTk-3F-SEC" id="86P-vn-8mz"/>
|
||||
<outlet property="msgTextViewLeadingConstraint" destination="uig-Xh-7m6" id="kgj-3v-ECW"/>
|
||||
<outlet property="msgTextViewMinHeightConstraint" destination="SHB-dF-A5J" id="RjV-W7-QaK"/>
|
||||
<outlet property="msgTextViewTopConstraint" destination="mkw-3s-H8B" id="lON-oG-Xx9"/>
|
||||
<outlet property="msgTextViewTrailingConstraint" destination="Shz-6S-kGd" id="5ib-m6-Lna"/>
|
||||
<outlet property="msgTextViewWidthConstraint" destination="aQ3-Pg-LVD" id="JPV-up-dzy"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomOutgoingBubbleTableViewCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomOutgoingTextMsgBubbleCell` displays outgoing message bubbles with user's picture.
|
||||
*/
|
||||
@interface MXKRoomOutgoingTextMsgBubbleCell : MXKRoomOutgoingBubbleTableViewCell
|
||||
|
||||
@end
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomOutgoingTextMsgBubbleCell.h"
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@implementation MXKRoomOutgoingTextMsgBubbleCell
|
||||
|
||||
- (void)setupViews
|
||||
{
|
||||
[super setupViews];
|
||||
|
||||
RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared];
|
||||
|
||||
[timelineConfiguration.currentStyle.cellLayoutUpdater setupLayoutForOutgoingTextMessageCell:self];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="pad-g3-2YJ" customClass="MXKRoomOutgoingTextMsgBubbleCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="pad-g3-2YJ" id="fCg-ju-gnG">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="49.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="ezT-Dl-ESR" userLabel="Picture View" customClass="MXKImageView">
|
||||
<rect key="frame" x="552" y="5" width="40" height="40"/>
|
||||
<color key="backgroundColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="40" id="JHc-dD-geb"/>
|
||||
<constraint firstAttribute="height" constant="40" id="lFb-Jo-C7R"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" text="text message" translatesAutoresizingMaskIntoConstraints="NO" id="tgO-Rv-C7R" customClass="MXKMessageTextView">
|
||||
<rect key="frame" x="452" y="10" width="97" height="39.5"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="39" id="2xF-Uv-zZv"/>
|
||||
<constraint firstAttribute="width" constant="97" id="ghN-E7-j4d"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
||||
</textView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LVJ-Av-zVs" userLabel="showHideDateTime">
|
||||
<rect key="frame" x="0.0" y="0.0" width="69" height="49.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="69" id="ghQ-Qb-BBg"/>
|
||||
</constraints>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="showHideDateTime:" destination="pad-g3-2YJ" eventType="touchUpInside" id="Ztw-z5-zlU"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="a51-cR-7FE" userLabel="bubbleInfoContainer">
|
||||
<rect key="frame" x="8" y="10" width="61" height="39.5"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="61" id="fDy-iL-hrD"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="ezT-Dl-ESR" secondAttribute="trailing" constant="8" id="3Pd-Qy-Xva"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tgO-Rv-C7R" secondAttribute="bottom" id="7C3-Tl-mMq"/>
|
||||
<constraint firstItem="tgO-Rv-C7R" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="10" id="8Sy-eu-tYs"/>
|
||||
<constraint firstItem="a51-cR-7FE" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" constant="8" id="E3x-h8-GPF"/>
|
||||
<constraint firstItem="LVJ-Av-zVs" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" id="Hve-E3-z5N"/>
|
||||
<constraint firstAttribute="bottom" secondItem="LVJ-Av-zVs" secondAttribute="bottom" id="IKr-Dc-HKz"/>
|
||||
<constraint firstItem="ezT-Dl-ESR" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="5" id="aHl-KA-68x"/>
|
||||
<constraint firstItem="a51-cR-7FE" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" constant="10" id="fQv-07-Pgx"/>
|
||||
<constraint firstItem="tgO-Rv-C7R" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="fCg-ju-gnG" secondAttribute="leading" constant="69" id="hwr-aa-TB4"/>
|
||||
<constraint firstItem="LVJ-Av-zVs" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" id="pYO-hi-P72"/>
|
||||
<constraint firstAttribute="bottom" secondItem="a51-cR-7FE" secondAttribute="bottom" id="viZ-Sx-3RW"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tgO-Rv-C7R" secondAttribute="trailing" constant="51" id="xYz-lp-c7K"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="bubbleInfoContainer" destination="a51-cR-7FE" id="wrR-cU-DVm"/>
|
||||
<outlet property="bubbleInfoContainerTopConstraint" destination="fQv-07-Pgx" id="82c-KH-Wop"/>
|
||||
<outlet property="messageTextView" destination="tgO-Rv-C7R" id="LZ5-hQ-AbQ"/>
|
||||
<outlet property="msgTextViewBottomConstraint" destination="7C3-Tl-mMq" id="wCR-UC-iq8"/>
|
||||
<outlet property="msgTextViewLeadingConstraint" destination="hwr-aa-TB4" id="c9j-8p-cpx"/>
|
||||
<outlet property="msgTextViewMinHeightConstraint" destination="2xF-Uv-zZv" id="t2t-18-GqU"/>
|
||||
<outlet property="msgTextViewTopConstraint" destination="8Sy-eu-tYs" id="7yx-oJ-KBP"/>
|
||||
<outlet property="msgTextViewTrailingConstraint" destination="xYz-lp-c7K" id="ubt-P4-J2o"/>
|
||||
<outlet property="msgTextViewWidthConstraint" destination="ghN-E7-j4d" id="Dic-6M-yCy"/>
|
||||
<outlet property="pictureView" destination="ezT-Dl-ESR" id="YsO-Kp-xaD"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomOutgoingTextMsgBubbleCell.h"
|
||||
|
||||
/**
|
||||
`MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell` displays outgoing message bubbles without user's name.
|
||||
*/
|
||||
@interface MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell : MXKRoomOutgoingTextMsgBubbleCell
|
||||
|
||||
@end
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h"
|
||||
|
||||
@implementation MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell
|
||||
|
||||
@end
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="pad-g3-2YJ" customClass="MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="pad-g3-2YJ" id="fCg-ju-gnG">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="34.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" text="text message" translatesAutoresizingMaskIntoConstraints="NO" id="tgO-Rv-C7R" customClass="MXKMessageTextView">
|
||||
<rect key="frame" x="452" y="0.0" width="97" height="34.5"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="97" id="QpI-TQ-x5C"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="34" id="ur4-ZU-uyL"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
||||
</textView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LVJ-Av-zVs" userLabel="showHideDateTime">
|
||||
<rect key="frame" x="0.0" y="0.0" width="69" height="34.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="69" id="ghQ-Qb-BBg"/>
|
||||
</constraints>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="showHideDateTime:" destination="pad-g3-2YJ" eventType="touchUpInside" id="Ztw-z5-zlU"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="a51-cR-7FE" userLabel="bubbleInfoContainer">
|
||||
<rect key="frame" x="8" y="0.0" width="61" height="34.5"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="61" id="fDy-iL-hrD"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="tgO-Rv-C7R" secondAttribute="bottom" id="7C3-Tl-mMq"/>
|
||||
<constraint firstItem="tgO-Rv-C7R" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" id="8Sy-eu-tYs"/>
|
||||
<constraint firstItem="a51-cR-7FE" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" constant="8" id="E3x-h8-GPF"/>
|
||||
<constraint firstItem="LVJ-Av-zVs" firstAttribute="leading" secondItem="fCg-ju-gnG" secondAttribute="leading" id="Hve-E3-z5N"/>
|
||||
<constraint firstAttribute="bottom" secondItem="LVJ-Av-zVs" secondAttribute="bottom" id="IKr-Dc-HKz"/>
|
||||
<constraint firstItem="a51-cR-7FE" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" id="fQv-07-Pgx"/>
|
||||
<constraint firstItem="tgO-Rv-C7R" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="fCg-ju-gnG" secondAttribute="leading" constant="69" id="hwr-aa-TB4"/>
|
||||
<constraint firstItem="LVJ-Av-zVs" firstAttribute="top" secondItem="fCg-ju-gnG" secondAttribute="top" id="pYO-hi-P72"/>
|
||||
<constraint firstAttribute="bottom" secondItem="a51-cR-7FE" secondAttribute="bottom" id="viZ-Sx-3RW"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tgO-Rv-C7R" secondAttribute="trailing" constant="51" id="xYz-lp-c7K"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<outlet property="bubbleInfoContainer" destination="a51-cR-7FE" id="wrR-cU-DVm"/>
|
||||
<outlet property="bubbleInfoContainerTopConstraint" destination="fQv-07-Pgx" id="82c-KH-Wop"/>
|
||||
<outlet property="messageTextView" destination="tgO-Rv-C7R" id="LZ5-hQ-AbQ"/>
|
||||
<outlet property="msgTextViewBottomConstraint" destination="7C3-Tl-mMq" id="ReW-nS-1Jc"/>
|
||||
<outlet property="msgTextViewLeadingConstraint" destination="hwr-aa-TB4" id="c9j-8p-cpx"/>
|
||||
<outlet property="msgTextViewMinHeightConstraint" destination="ur4-ZU-uyL" id="gIe-dR-6cb"/>
|
||||
<outlet property="msgTextViewTopConstraint" destination="8Sy-eu-tYs" id="7yx-oJ-KBP"/>
|
||||
<outlet property="msgTextViewTrailingConstraint" destination="xYz-lp-c7K" id="ubt-P4-J2o"/>
|
||||
<outlet property="msgTextViewWidthConstraint" destination="QpI-TQ-x5C" id="6JK-pz-IWm"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
+5
-5
@@ -18,7 +18,7 @@ import Foundation
|
||||
import Reusable
|
||||
|
||||
@objcMembers
|
||||
class FromThreadView: UIView {
|
||||
class FromAThreadView: UIView {
|
||||
|
||||
private enum Constants {
|
||||
static let viewHeight: CGFloat = 18
|
||||
@@ -32,8 +32,8 @@ class FromThreadView: UIView {
|
||||
return Constants.viewHeight
|
||||
}
|
||||
|
||||
static func instantiate() -> FromThreadView {
|
||||
let view = FromThreadView.loadFromNib()
|
||||
static func instantiate() -> FromAThreadView {
|
||||
let view = FromAThreadView.loadFromNib()
|
||||
view.update(theme: ThemeService.shared().theme)
|
||||
view.titleLabel.text = VectorL10n.messageFromAThread
|
||||
return view
|
||||
@@ -41,9 +41,9 @@ class FromThreadView: UIView {
|
||||
|
||||
}
|
||||
|
||||
extension FromThreadView: NibLoadable {}
|
||||
extension FromAThreadView: NibLoadable {}
|
||||
|
||||
extension FromThreadView: Themable {
|
||||
extension FromAThreadView: Themable {
|
||||
|
||||
func update(theme: Theme) {
|
||||
backgroundColor = .clear
|
||||
+8
-8
@@ -11,22 +11,22 @@
|
||||
<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="FromThreadView" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="139" height="44"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="FromAThreadView" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="139" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="gZf-Nh-De6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="139" height="44"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="139" height="18"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="threads_icon" translatesAutoresizingMaskIntoConstraints="NO" id="cdy-fz-kjn">
|
||||
<rect key="frame" x="0.0" y="0.0" width="18" height="44"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="18" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="18" id="3mH-It-De7"/>
|
||||
<constraint firstAttribute="width" constant="18" id="Jzw-cL-zxG"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="From a thread" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fX6-Xz-I4e">
|
||||
<rect key="frame" x="22" y="0.0" width="117" height="44"/>
|
||||
<rect key="frame" x="22" y="0.0" width="117" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="13"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -38,16 +38,16 @@
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="gZf-Nh-De6" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="0Hy-t1-GHo"/>
|
||||
<constraint firstAttribute="trailing" secondItem="gZf-Nh-De6" secondAttribute="trailing" id="ELX-qi-dTm"/>
|
||||
<constraint firstAttribute="bottom" secondItem="gZf-Nh-De6" secondAttribute="bottom" id="Pye-fH-Zny"/>
|
||||
<constraint firstItem="gZf-Nh-De6" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="b2i-tg-f7D"/>
|
||||
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="gZf-Nh-De6" secondAttribute="trailing" id="w9I-0I-lD2"/>
|
||||
<constraint firstItem="gZf-Nh-De6" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="dWk-cp-fYS"/>
|
||||
</constraints>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<connections>
|
||||
<outlet property="iconView" destination="cdy-fz-kjn" id="Kev-ko-oTu"/>
|
||||
<outlet property="titleLabel" destination="fX6-Xz-I4e" id="65X-PJ-RpF"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-119.56521739130436" y="-252.45535714285714"/>
|
||||
<point key="canvasLocation" x="-119.56521739130436" y="-257.47767857142856"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
+4
-4
@@ -16,8 +16,8 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
struct ThreadSummaryViewModel {
|
||||
var numberOfReplies: Int
|
||||
var lastMessageSenderAvatar: AvatarViewDataProtocol?
|
||||
var lastMessageText: NSAttributedString?
|
||||
struct ThreadSummaryModel {
|
||||
let numberOfReplies: Int
|
||||
let lastMessageSenderAvatar: AvatarViewDataProtocol?
|
||||
let lastMessageText: NSAttributedString?
|
||||
}
|
||||
@@ -38,7 +38,7 @@ class ThreadSummaryView: UIView {
|
||||
@IBOutlet private weak var lastMessageContentLabel: UILabel!
|
||||
|
||||
private var theme: Theme = ThemeService.shared().theme
|
||||
private(set) var thread: MXThread!
|
||||
private(set) var thread: MXThread?
|
||||
|
||||
private lazy var tapGestureRecognizer: UITapGestureRecognizer = {
|
||||
return UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
|
||||
@@ -56,9 +56,10 @@ class ThreadSummaryView: UIView {
|
||||
loadNibContent()
|
||||
update(theme: ThemeService.shared().theme)
|
||||
configure()
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
static func contentViewHeight(forThread thread: MXThread, fitting maxWidth: CGFloat) -> CGFloat {
|
||||
static func contentViewHeight(forThread thread: MXThread?, fitting maxWidth: CGFloat) -> CGFloat {
|
||||
return RoomBubbleCellLayout.threadSummaryViewHeight
|
||||
}
|
||||
|
||||
@@ -67,14 +68,14 @@ class ThreadSummaryView: UIView {
|
||||
loadNibContent()
|
||||
}
|
||||
|
||||
@nonobjc func configure(withViewModel viewModel: ThreadSummaryViewModel) {
|
||||
numberOfRepliesLabel.text = String(viewModel.numberOfReplies)
|
||||
if let avatar = viewModel.lastMessageSenderAvatar {
|
||||
@nonobjc func configure(withModel model: ThreadSummaryModel) {
|
||||
numberOfRepliesLabel.text = String(model.numberOfReplies)
|
||||
if let avatar = model.lastMessageSenderAvatar {
|
||||
lastMessageAvatarView.fill(with: avatar)
|
||||
} else {
|
||||
lastMessageAvatarView.avatarImageView.image = nil
|
||||
}
|
||||
if let lastMessage = viewModel.lastMessageText {
|
||||
if let lastMessage = model.lastMessageText {
|
||||
let mutable = NSMutableAttributedString(attributedString: lastMessage)
|
||||
mutable.setAttributes([
|
||||
.font: Constants.lastMessageFont
|
||||
@@ -116,10 +117,10 @@ class ThreadSummaryView: UIView {
|
||||
with: roomState,
|
||||
error: formatterError)
|
||||
|
||||
let viewModel = ThreadSummaryViewModel(numberOfReplies: thread.numberOfReplies,
|
||||
lastMessageSenderAvatar: avatarViewData,
|
||||
lastMessageText: lastMessageText)
|
||||
self.configure(withViewModel: viewModel)
|
||||
let model = ThreadSummaryModel(numberOfReplies: thread.numberOfReplies,
|
||||
lastMessageSenderAvatar: avatarViewData,
|
||||
lastMessageText: lastMessageText)
|
||||
self.configure(withModel: model)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,8 +133,6 @@ class ThreadSummaryView: UIView {
|
||||
}
|
||||
}
|
||||
|
||||
// extension ThreadSummaryView: NibLoadable {}
|
||||
|
||||
extension ThreadSummaryView: NibOwnerLoadable {}
|
||||
|
||||
extension ThreadSummaryView: Themable {
|
||||
|
||||
+7
-7
@@ -16,12 +16,12 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
struct ThreadRoomTitleViewModel {
|
||||
var roomAvatar: AvatarViewDataProtocol?
|
||||
var roomEncryptionBadge: UIImage?
|
||||
var roomDisplayName: String?
|
||||
struct ThreadRoomTitleModel {
|
||||
let roomAvatar: AvatarViewDataProtocol?
|
||||
let roomEncryptionBadge: UIImage?
|
||||
let roomDisplayName: String?
|
||||
|
||||
static let empty = ThreadRoomTitleViewModel(roomAvatar: nil,
|
||||
roomEncryptionBadge: nil,
|
||||
roomDisplayName: nil)
|
||||
static let empty = ThreadRoomTitleModel(roomAvatar: nil,
|
||||
roomEncryptionBadge: nil,
|
||||
roomDisplayName: nil)
|
||||
}
|
||||
@@ -38,15 +38,15 @@ class ThreadRoomTitleView: RoomTitleView {
|
||||
|
||||
// MARK: - Methods
|
||||
|
||||
func configure(withViewModel viewModel: ThreadRoomTitleViewModel) {
|
||||
if let avatarViewData = viewModel.roomAvatar {
|
||||
func configure(withModel model: ThreadRoomTitleModel) {
|
||||
if let avatarViewData = model.roomAvatar {
|
||||
roomAvatarView.fill(with: avatarViewData)
|
||||
} else {
|
||||
roomAvatarView.avatarImageView.image = nil
|
||||
}
|
||||
roomEncryptionBadgeView.image = viewModel.roomEncryptionBadge
|
||||
roomEncryptionBadgeView.isHidden = viewModel.roomEncryptionBadge == nil
|
||||
roomNameLabel.text = viewModel.roomDisplayName
|
||||
roomEncryptionBadgeView.image = model.roomEncryptionBadge
|
||||
roomEncryptionBadgeView.isHidden = model.roomEncryptionBadge == nil
|
||||
roomNameLabel.text = model.roomDisplayName
|
||||
}
|
||||
|
||||
// MARK: - Overrides
|
||||
@@ -81,10 +81,10 @@ class ThreadRoomTitleView: RoomTitleView {
|
||||
encrpytionBadge = nil
|
||||
}
|
||||
|
||||
let viewModel = ThreadRoomTitleViewModel(roomAvatar: avatarViewData,
|
||||
roomEncryptionBadge: encrpytionBadge,
|
||||
roomDisplayName: room.displayName)
|
||||
configure(withViewModel: viewModel)
|
||||
let model = ThreadRoomTitleModel(roomAvatar: avatarViewData,
|
||||
roomEncryptionBadge: encrpytionBadge,
|
||||
roomDisplayName: room.displayName)
|
||||
configure(withModel: model)
|
||||
}
|
||||
|
||||
override func awakeFromNib() {
|
||||
|
||||
Reference in New Issue
Block a user