mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Call notifications are deletable
// FREEBIE
This commit is contained in:
parent
405990a7d5
commit
7106eee4a3
|
@ -4,6 +4,10 @@
|
|||
#import "OWSMessageData.h"
|
||||
#import "TSMessageAdapter.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class TSCall;
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
kCallOutgoing = 1,
|
||||
kCallIncoming = 2,
|
||||
|
@ -15,6 +19,18 @@ typedef enum : NSUInteger {
|
|||
|
||||
@interface OWSCall : NSObject <OWSMessageData, NSCoding, NSCopying>
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (instancetype)initWithCallRecord:(TSCall *)callRecord;
|
||||
|
||||
- (instancetype)initWithCallerId:(NSString *)callerId
|
||||
callerDisplayName:(NSString *)callerDisplayName
|
||||
date:(nullable NSDate *)date
|
||||
status:(CallStatus)status
|
||||
displayString:(NSString *)detailString NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/*
|
||||
* Returns the string Id of the user who initiated the call
|
||||
*/
|
||||
|
@ -41,14 +57,8 @@ typedef enum : NSUInteger {
|
|||
*/
|
||||
@property (nonatomic, copy) NSString *detailString;
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (instancetype)initWithCallerId:(NSString *)callerId
|
||||
callerDisplayName:(NSString *)callerDisplayName
|
||||
date:(NSDate *)date
|
||||
status:(CallStatus)status
|
||||
displayString:(NSString *)detailString NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (NSString *)dateText;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -2,8 +2,13 @@
|
|||
// Portions Copyright (c) 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSCall.h"
|
||||
#import "TSCall.h"
|
||||
#import "TSContactThread.h"
|
||||
#import <JSQMessagesViewController/JSQMessagesTimestampFormatter.h>
|
||||
#import <JSQMessagesViewController/UIImage+JSQMessages.h>
|
||||
#import <SignalServiceKit/TSCall.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSCall ()
|
||||
|
||||
|
@ -13,6 +18,7 @@
|
|||
@property (nonatomic) BOOL shouldStartExpireTimer;
|
||||
@property (nonatomic) uint64_t expiresAtSeconds;
|
||||
@property (nonatomic) uint32_t expiresInSeconds;
|
||||
@property (nonatomic) TSInteraction *interaction;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -20,19 +26,68 @@
|
|||
|
||||
#pragma mark - Initialzation
|
||||
|
||||
- (id)init
|
||||
- (instancetype)initWithCallRecord:(TSCall *)callRecord
|
||||
{
|
||||
NSAssert(NO,
|
||||
@"%s is not a valid initializer for %@. Use %@ instead",
|
||||
__PRETTY_FUNCTION__,
|
||||
[self class],
|
||||
NSStringFromSelector(@selector(initWithCallerId:callerDisplayName:date:status:displayString:)));
|
||||
return [self initWithCallerId:nil callerDisplayName:nil date:nil status:0 displayString:nil];
|
||||
TSThread *thread = callRecord.thread;
|
||||
TSContactThread *contactThread;
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
contactThread = (TSContactThread *)thread;
|
||||
} else {
|
||||
DDLogError(@"%@ Unexpected thread type: %@", self.tag, thread);
|
||||
}
|
||||
|
||||
|
||||
CallStatus status = 0;
|
||||
switch (callRecord.callType) {
|
||||
case RPRecentCallTypeOutgoing:
|
||||
status = kCallOutgoing;
|
||||
break;
|
||||
case RPRecentCallTypeMissed:
|
||||
status = kCallMissed;
|
||||
break;
|
||||
case RPRecentCallTypeIncoming:
|
||||
status = kCallIncoming;
|
||||
break;
|
||||
default:
|
||||
status = kCallIncoming;
|
||||
break;
|
||||
}
|
||||
|
||||
NSString *name = contactThread.name;
|
||||
NSString *detailString;
|
||||
switch (status) {
|
||||
case kCallMissed:
|
||||
detailString = [NSString stringWithFormat:NSLocalizedString(@"MSGVIEW_MISSED_CALL", nil), name];
|
||||
break;
|
||||
case kCallIncoming:
|
||||
detailString = [NSString stringWithFormat:NSLocalizedString(@"MSGVIEW_RECEIVED_CALL", nil), name];
|
||||
break;
|
||||
case kCallOutgoing:
|
||||
detailString = [NSString stringWithFormat:NSLocalizedString(@"MSGVIEW_YOU_CALLED", nil), name];
|
||||
break;
|
||||
default:
|
||||
detailString = @"";
|
||||
break;
|
||||
}
|
||||
|
||||
self = [self initWithCallerId:contactThread.contactIdentifier
|
||||
callerDisplayName:name
|
||||
date:callRecord.date
|
||||
status:status
|
||||
displayString:detailString];
|
||||
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_interaction = callRecord;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCallerId:(NSString *)senderId
|
||||
callerDisplayName:(NSString *)senderDisplayName
|
||||
date:(NSDate *)date
|
||||
date:(nullable NSDate *)date
|
||||
status:(CallStatus)status
|
||||
displayString:(NSString *)detailString
|
||||
{
|
||||
|
@ -105,11 +160,18 @@
|
|||
|
||||
- (BOOL)canPerformEditingAction:(SEL)action
|
||||
{
|
||||
return NO;
|
||||
return action == @selector(delete:);
|
||||
}
|
||||
|
||||
- (void)performEditingAction:(SEL)action
|
||||
{
|
||||
// Deletes are always handled by TSMessageAdapter
|
||||
if (action == @selector(delete:)) {
|
||||
DDLogDebug(@"%@ Deleting interaction with uniqueId: %@", self.tag, self.interaction.uniqueId);
|
||||
[self.interaction remove];
|
||||
return;
|
||||
}
|
||||
|
||||
// Shouldn't get here, as only supported actions should be exposed via canPerformEditingAction
|
||||
NSString *actionString = NSStringFromSelector(action);
|
||||
DDLogError(@"%@ '%@' action unsupported", self.tag, actionString);
|
||||
|
@ -124,7 +186,7 @@
|
|||
|
||||
#pragma mark - NSCoding
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder
|
||||
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
|
||||
{
|
||||
NSString *senderId = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(senderId))];
|
||||
NSString *senderDisplayName = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(senderDisplayName))];
|
||||
|
@ -149,7 +211,7 @@
|
|||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone
|
||||
- (instancetype)copyWithZone:(nullable NSZone *)zone
|
||||
{
|
||||
return [[[self class] allocWithZone:zone] initWithCallerId:self.senderId
|
||||
callerDisplayName:self.senderDisplayName
|
||||
|
@ -181,3 +243,5 @@
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSMessagesBubblesSizeCalculator.h"
|
||||
#import "OWSCall.h"
|
||||
#import "OWSDisplayedMessageCollectionViewCell.h"
|
||||
#import "TSMessageAdapter.h"
|
||||
#import "UIFont+OWS.h"
|
||||
|
@ -49,6 +50,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
}
|
||||
|
||||
if ([messageData isKindOfClass:[OWSCall class]]) {
|
||||
return [self messageBubbleSizeForCallData:messageData atIndexPath:indexPath withLayout:layout];
|
||||
}
|
||||
|
||||
CGSize size;
|
||||
// BEGIN HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
BOOL isIOS10OrGreater =
|
||||
|
@ -243,6 +248,39 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return finalSize;
|
||||
}
|
||||
|
||||
- (CGSize)messageBubbleSizeForCallData:(id<JSQMessageData>)messageData
|
||||
atIndexPath:(NSIndexPath *)indexPath
|
||||
withLayout:(JSQMessagesCollectionViewFlowLayout *)layout
|
||||
{
|
||||
NSValue *cachedSize = [self.cache objectForKey:@([messageData messageHash])];
|
||||
if (cachedSize != nil) {
|
||||
return [cachedSize CGSizeValue];
|
||||
}
|
||||
|
||||
CGFloat horizontalInsetsTotal = 0.0;
|
||||
CGFloat maximumTextWidth = [self textBubbleWidthForLayout:layout] - horizontalInsetsTotal;
|
||||
|
||||
CGRect stringRect = [[messageData text]
|
||||
boundingRectWithSize:CGSizeMake(maximumTextWidth, CGFLOAT_MAX)
|
||||
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
|
||||
attributes:@{
|
||||
NSFontAttributeName : [UIFont ows_dynamicTypeBodyFont]
|
||||
} // Hack to use a slightly larger than actual font, because I'm seeing messages with higher line
|
||||
// count get clipped.
|
||||
context:nil];
|
||||
|
||||
CGSize stringSize = CGRectIntegral(stringRect).size;
|
||||
|
||||
CGFloat verticalInsets = 0;
|
||||
CGFloat finalWidth = maximumTextWidth + horizontalInsetsTotal;
|
||||
|
||||
CGSize finalSize = CGSizeMake(finalWidth, stringSize.height + verticalInsets);
|
||||
|
||||
[self.cache setObject:[NSValue valueWithCGSize:finalSize] forKey:@([messageData messageHash])];
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -19,6 +19,7 @@ typedef NS_ENUM(NSInteger, TSMessageAdapterType) {
|
|||
@protocol OWSMessageData <JSQMessageData, OWSMessageEditing>
|
||||
|
||||
@property (nonatomic, readonly) TSMessageAdapterType messageType;
|
||||
@property (nonatomic, readonly) TSInteraction *interaction;
|
||||
@property (nonatomic, readonly) BOOL isExpiringMessage;
|
||||
@property (nonatomic, readonly) BOOL shouldStartExpireTimer;
|
||||
@property (nonatomic, readonly) uint64_t expiresAtSeconds;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
// Created by Michael Kirk on 3/11/16.
|
||||
|
||||
@class TSInteraction;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol OWSMessageEditing <NSObject>
|
||||
|
|
|
@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
+ (id<OWSMessageData>)messageViewDataWithInteraction:(TSInteraction *)interaction inThread:(TSThread *)thread;
|
||||
|
||||
@property TSInteraction *interaction;
|
||||
@property (nonatomic) TSInteraction *interaction;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -169,10 +169,8 @@
|
|||
}
|
||||
}
|
||||
} else if ([interaction isKindOfClass:[TSCall class]]) {
|
||||
adapter.messageBody = @"Placeholder for TSCalls";
|
||||
adapter.messageType = TSCallAdapter;
|
||||
OWSCall *call = [self owsCallForTSCall:(TSCall *)interaction thread:(TSContactThread *)thread];
|
||||
return call;
|
||||
TSCall *callRecord = (TSCall *)interaction;
|
||||
return [[OWSCall alloc] initWithCallRecord:callRecord];
|
||||
} else if ([interaction isKindOfClass:[TSInfoMessage class]]) {
|
||||
TSInfoMessage *infoMessage = (TSInfoMessage *)interaction;
|
||||
adapter.infoMessageType = infoMessage.messageType;
|
||||
|
@ -209,48 +207,6 @@
|
|||
return adapter;
|
||||
}
|
||||
|
||||
+ (OWSCall *)owsCallForTSCall:(TSCall *)call thread:(TSContactThread *)thread {
|
||||
CallStatus status = 0;
|
||||
NSString *name = thread.name;
|
||||
NSString *detailString = @"";
|
||||
|
||||
switch (call.callType) {
|
||||
case RPRecentCallTypeOutgoing:
|
||||
status = kCallOutgoing;
|
||||
break;
|
||||
case RPRecentCallTypeMissed:
|
||||
status = kCallMissed;
|
||||
break;
|
||||
case RPRecentCallTypeIncoming:
|
||||
status = kCallIncoming;
|
||||
break;
|
||||
default:
|
||||
status = kCallIncoming;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case kCallMissed:
|
||||
detailString = [NSString stringWithFormat:NSLocalizedString(@"MSGVIEW_MISSED_CALL", nil), name];
|
||||
break;
|
||||
case kCallIncoming:
|
||||
detailString = [NSString stringWithFormat:NSLocalizedString(@"MSGVIEW_RECEIVED_CALL", nil), name];
|
||||
break;
|
||||
case kCallOutgoing:
|
||||
detailString = [NSString stringWithFormat:NSLocalizedString(@"MSGVIEW_YOU_CALLED", nil), name];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
OWSCall *owsCall = [[OWSCall alloc] initWithCallerId:thread.contactIdentifier
|
||||
callerDisplayName:thread.name
|
||||
date:call.date
|
||||
status:status
|
||||
displayString:detailString];
|
||||
return owsCall;
|
||||
}
|
||||
|
||||
- (NSString *)senderId {
|
||||
if (_senderId) {
|
||||
return _senderId;
|
||||
|
|
|
@ -829,12 +829,18 @@ typedef enum : NSUInteger {
|
|||
[attributedText setAttributes:@{ NSFontAttributeName: regularFont }
|
||||
range:range];
|
||||
}
|
||||
callCell.cellLabel.attributedText = attributedText;
|
||||
callCell.cellLabel.numberOfLines = 0; // uses as many lines as it needs
|
||||
callCell.cellLabel.textColor = [UIColor ows_materialBlueColor];
|
||||
callCell.textView.text = nil;
|
||||
callCell.textView.attributedText = attributedText;
|
||||
|
||||
callCell.textView.textAlignment = NSTextAlignmentCenter;
|
||||
callCell.textView.textColor = [UIColor ows_materialBlueColor];
|
||||
callCell.layer.shouldRasterize = YES;
|
||||
callCell.layer.rasterizationScale = [UIScreen mainScreen].scale;
|
||||
|
||||
// Disable text selectability. Specifying this in prepareForReuse/awakeFromNib was not sufficient.
|
||||
callCell.textView.userInteractionEnabled = NO;
|
||||
callCell.textView.selectable = NO;
|
||||
|
||||
return callCell;
|
||||
}
|
||||
|
||||
|
@ -865,6 +871,7 @@ typedef enum : NSUInteger {
|
|||
// Disable text selectability. Specifying this in prepareForReuse/awakeFromNib was not sufficient.
|
||||
infoCell.textView.userInteractionEnabled = NO;
|
||||
infoCell.textView.selectable = NO;
|
||||
|
||||
infoCell.messageBubbleContainerView.layer.borderColor = [[UIColor ows_infoMessageBorderColor] CGColor];
|
||||
infoCell.headerImageView.image = [UIImage imageNamed:@"warning_white"];
|
||||
|
||||
|
@ -876,9 +883,11 @@ typedef enum : NSUInteger {
|
|||
{
|
||||
OWSDisplayedMessageCollectionViewCell *errorCell = [self loadDisplayedMessageCollectionViewCellForIndexPath:indexPath];
|
||||
errorCell.textView.text = [errorMessage text];
|
||||
|
||||
// Disable text selectability. Specifying this in prepareForReuse/awakeFromNib was not sufficient.
|
||||
errorCell.textView.userInteractionEnabled = NO;
|
||||
errorCell.textView.selectable = NO;
|
||||
|
||||
errorCell.messageBubbleContainerView.layer.borderColor = [[UIColor ows_errorMessageBorderColor] CGColor];
|
||||
errorCell.headerImageView.image = [UIImage imageNamed:@"error_white"];
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Portions Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSCallCollectionViewCell.h"
|
||||
#import "UIColor+OWS.h"
|
||||
#import <JSQMessagesViewController/JSQMessagesCollectionViewLayoutAttributes.h>
|
||||
#import <JSQMessagesViewController/UIView+JSQMessages.h>
|
||||
|
||||
@interface OWSCallCollectionViewCell ()
|
||||
|
@ -31,23 +33,19 @@
|
|||
- (void)awakeFromNib
|
||||
{
|
||||
[super awakeFromNib];
|
||||
self.textView.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:12.0f];
|
||||
|
||||
[self setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
self.cellLabel.textAlignment = NSTextAlignmentCenter;
|
||||
self.cellLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:14.0f];
|
||||
self.cellLabel.textColor = [UIColor lightGrayColor];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Collection view cell
|
||||
|
||||
- (void)prepareForReuse
|
||||
{
|
||||
[super prepareForReuse];
|
||||
self.cellLabel.text = nil;
|
||||
}
|
||||
|
||||
- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
|
||||
{
|
||||
// override superclass with no-op which resets our attributed font on layout.
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11201" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
|
@ -14,46 +15,56 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="320" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YEr-eC-P6i" customClass="JSQMessagesLabel">
|
||||
<rect key="frame" x="39" y="0.0" width="242" height="20"/>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ErD-Uv-aKj">
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="o2l-Ms-1mk">
|
||||
<frame key="frameInset" minX="293" width="20" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="78L-mQ-gEo"/>
|
||||
<constraint firstAttribute="width" constant="20" id="olH-5o-XyR"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="H8m-r4-eEC">
|
||||
<frame key="frameInset" minX="7" width="20" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="Qay-jM-aBk"/>
|
||||
<constraint firstAttribute="width" constant="20" id="RpE-jJ-cYX"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" text="You called Joe" textAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="R85-fN-3GC" customClass="JSQMessagesCellTextView">
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="105-nv-5Fw"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="7nw-w2-91p"/>
|
||||
<constraint firstItem="H8m-r4-eEC" firstAttribute="leading" secondItem="ErD-Uv-aKj" secondAttribute="leading" constant="6" id="8pe-Zh-bRn"/>
|
||||
<constraint firstItem="R85-fN-3GC" firstAttribute="top" secondItem="ErD-Uv-aKj" secondAttribute="top" id="US4-6n-Kmr"/>
|
||||
<constraint firstItem="o2l-Ms-1mk" firstAttribute="leading" secondItem="R85-fN-3GC" secondAttribute="trailing" id="WKY-HI-dAT"/>
|
||||
<constraint firstAttribute="trailing" secondItem="o2l-Ms-1mk" secondAttribute="trailing" constant="6" id="ZFy-4i-25N"/>
|
||||
<constraint firstItem="R85-fN-3GC" firstAttribute="centerX" secondItem="ErD-Uv-aKj" secondAttribute="centerX" id="app-de-yA3"/>
|
||||
<constraint firstAttribute="bottom" secondItem="R85-fN-3GC" secondAttribute="bottom" id="dyS-Re-6e7"/>
|
||||
<constraint firstItem="H8m-r4-eEC" firstAttribute="trailing" secondItem="R85-fN-3GC" secondAttribute="leading" id="m7j-ui-ZMI"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="o2l-Ms-1mk">
|
||||
<rect key="frame" x="281" y="0.0" width="20" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="78L-mQ-gEo"/>
|
||||
<constraint firstAttribute="width" constant="20" id="olH-5o-XyR"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="H8m-r4-eEC">
|
||||
<rect key="frame" x="19" y="0.0" width="20" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="Qay-jM-aBk"/>
|
||||
<constraint firstAttribute="width" constant="20" id="RpE-jJ-cYX"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstItem="YEr-eC-P6i" firstAttribute="centerY" secondItem="o2l-Ms-1mk" secondAttribute="centerY" id="8wg-Tg-9Nh"/>
|
||||
<constraint firstAttribute="trailing" secondItem="YEr-eC-P6i" secondAttribute="trailing" constant="39" id="Hj7-z5-WMM"/>
|
||||
<constraint firstItem="YEr-eC-P6i" firstAttribute="leading" secondItem="H8m-r4-eEC" secondAttribute="trailing" id="ZZJ-jL-10d"/>
|
||||
<constraint firstItem="YEr-eC-P6i" firstAttribute="top" secondItem="Efo-Hk-7Hw" secondAttribute="top" id="rEI-cY-6lx"/>
|
||||
<constraint firstItem="YEr-eC-P6i" firstAttribute="leading" secondItem="Efo-Hk-7Hw" secondAttribute="leading" constant="39" id="uNd-aK-1hE"/>
|
||||
<constraint firstItem="YEr-eC-P6i" firstAttribute="centerY" secondItem="H8m-r4-eEC" secondAttribute="centerY" id="wg8-V9-pBf"/>
|
||||
<constraint firstItem="o2l-Ms-1mk" firstAttribute="leading" secondItem="YEr-eC-P6i" secondAttribute="trailing" id="wmR-MD-QeR"/>
|
||||
<constraint firstAttribute="bottom" secondItem="ErD-Uv-aKj" secondAttribute="bottom" id="5rh-PH-WZl"/>
|
||||
<constraint firstItem="ErD-Uv-aKj" firstAttribute="top" secondItem="Efo-Hk-7Hw" secondAttribute="top" id="TGa-7F-Fiw"/>
|
||||
<constraint firstItem="ErD-Uv-aKj" firstAttribute="leading" secondItem="Efo-Hk-7Hw" secondAttribute="leading" id="fnH-V7-ocW"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ErD-Uv-aKj" secondAttribute="trailing" id="nlh-Ve-1Sm"/>
|
||||
</constraints>
|
||||
<size key="customSize" width="320" height="20"/>
|
||||
<connections>
|
||||
<outlet property="cellLabel" destination="YEr-eC-P6i" id="jii-8O-zLL"/>
|
||||
<outlet property="incomingCallImageView" destination="H8m-r4-eEC" id="hVW-Ng-BnU"/>
|
||||
<outlet property="messageBubbleContainerView" destination="ErD-Uv-aKj" id="WSq-Wd-61K"/>
|
||||
<outlet property="outgoingCallImageView" destination="o2l-Ms-1mk" id="Q5m-uX-80H"/>
|
||||
<outlet property="textView" destination="R85-fN-3GC" id="Hry-eB-f6P"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="219" y="435"/>
|
||||
</collectionViewCell>
|
||||
|
|
Loading…
Reference in a new issue