Commit 98827a19 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk
Browse files

swarm: add invitation view

Change-Id: Idbc414eafc50127e8eb9d976226f1bdee81540c0
parent 3037dabb
......@@ -34,6 +34,11 @@ namespace lrc {
@interface ConversationVC : NSViewController <LeaveMessageDelegate>
/**
* KVO to switch between request/conversation view
*/
@property (assign)BOOL isRequest;
-(void) initFrame;
-(void) showWithAnimation:(BOOL)animate;
-(void) hideWithAnimation:(BOOL)animate;
......
......@@ -19,6 +19,7 @@
*/
#import "ConversationVC.h"
#import "delegates/ImageManipulationDelegate.h"
#import <qstring.h>
#import <QPixmap>
......@@ -27,6 +28,8 @@
#import <QuickLook/QuickLook.h>
#import <Quartz/Quartz.h>
#import <globalinstances.h>
#import "views/IconButton.h"
#import "views/HoverButton.h"
#import "views/IMTableCellView.h"
......@@ -47,6 +50,18 @@
__unsafe_unretained IBOutlet HoverButton *addContactButton;
__unsafe_unretained IBOutlet NSLayoutConstraint* sentContactRequestWidth;
// invitation view
__unsafe_unretained IBOutlet NSView* invitationView;
__unsafe_unretained IBOutlet NSImageView* invitationAvatar;
__unsafe_unretained IBOutlet NSTextField *invitationTitle;
__unsafe_unretained IBOutlet NSTextField *invitationMessage;
__unsafe_unretained IBOutlet NSTextField *invitationLabel;
__unsafe_unretained IBOutlet NSView *invitationBox;
__unsafe_unretained IBOutlet NSButton *invitationBlock;
__unsafe_unretained IBOutlet NSButton *invitationRefuse;
__unsafe_unretained IBOutlet NSButton *invitationAccept;
__unsafe_unretained IBOutlet NSStackView* invitationControls;
__unsafe_unretained IBOutlet NSButton* sentContactRequestButton;
IBOutlet MessagesVC* messagesViewVC;
LeaveMessageVC* leaveMessageVC;
......@@ -95,10 +110,47 @@ NSInteger const SEND_PANEL_MAX_HEIGHT = 120;
leaveMessageConversations = [[NSMutableArray alloc] init];
leaveMessageVC.delegate = self;
[messagesViewVC setAVModel: avModel];
//setup the invitation view
invitationView.wantsLayer = true;
invitationView.layer.backgroundColor = [[NSColor windowBackgroundColor] CGColor];
NSString *invitationText = NSLocalizedString(@"Hello, \nWould you like to join the conversation?", @"Incoming conversation request title");
[self setInvitationText: invitationText];
invitationBox.wantsLayer = true;
invitationBox.layer.cornerRadius = 20.0;
invitationBox.layer.backgroundColor = [[NSColor controlColor] CGColor];
invitationBox.shadow = [[NSShadow alloc] init];
invitationBox.layer.shadowOpacity = 0.2;
invitationBox.layer.shadowColor = [[NSColor colorWithRed:0 green:0 blue:0 alpha:0.3] CGColor];
invitationBox.layer.shadowOffset = NSMakeSize(0, -3);
invitationBox.layer.shadowRadius = 10;
[NSDistributedNotificationCenter.defaultCenter addObserver:self selector:@selector(themeChanged:) name:@"AppleInterfaceThemeChangedNotification" object: nil];
}
return self;
}
-(void) deinit {
[NSDistributedNotificationCenter.defaultCenter removeObserver:self];
}
-(void)themeChanged:(NSNotification *) notification {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
invitationBox.layer.backgroundColor = [[NSColor controlColor] CGColor];
invitationView.layer.backgroundColor = [[NSColor windowBackgroundColor] CGColor];
});
}
- (void)setInvitationText:(NSString*)text
{
NSFont *font = [NSFont systemFontOfSize: 18 weight: NSFontWeightMedium];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing: 4.0];
paragraphStyle.alignment = NSTextAlignmentCenter;
NSDictionary *attrDic = [NSDictionary dictionaryWithObjectsAndKeys: font, NSFontAttributeName, paragraphStyle, NSParagraphStyleAttributeName, [NSColor controlTextColor], NSForegroundColorAttributeName, nil];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString: text attributes:attrDic];
[invitationTitle setAttributedStringValue: attrString];
}
-(NSViewController*) getMessagesView {
return messagesViewVC;
}
......@@ -176,6 +228,11 @@ NSInteger const SEND_PANEL_MAX_HEIGHT = 120;
modelSortedConnection_ = QObject::connect(convModel_, &lrc::api::ConversationModel::modelChanged,
[self](){
cachedConv_ = nil;
auto* conv = [self getCurrentConversation];
if (conv == nil)
return;
[self updateInvitationView: conv];
});
filterChangedConnection_ = QObject::connect(convModel_, &lrc::api::ConversationModel::filterChanged,
[self](){
......@@ -184,6 +241,11 @@ NSInteger const SEND_PANEL_MAX_HEIGHT = 120;
newConversationConnection_ = QObject::connect(convModel_, &lrc::api::ConversationModel::newConversation,
[self](){
cachedConv_ = nil;
auto* conv = [self getCurrentConversation];
if (conv == nil)
return;
[self updateInvitationView: conv];
});
conversationRemovedConnection_ = QObject::connect(convModel_, &lrc::api::ConversationModel::conversationRemoved,
[self](){
......@@ -210,11 +272,52 @@ NSInteger const SEND_PANEL_MAX_HEIGHT = 120;
try {
[addContactButton setHidden:((convModel_->owner.contactModel->getContact(conv->participants[0]).profileInfo.type != lrc::api::profile::Type::TEMPORARY) || accountType == lrc::api::profile::Type::SIP)];
} catch (std::out_of_range& e) {
[addContactButton setHidden: true];
NSLog(@"contact out of range");
}
if (!conv->allMessagesLoaded) {
convModel_->loadConversationMessages(convUid_, 0);
}
@autoreleasepool {
auto& imageManip = reinterpret_cast<Interfaces::ImageManipulationDelegate&>(GlobalInstances::pixmapManipulator());
auto image = QtMac::toNSImage(qvariant_cast<QPixmap>(imageManip.conversationPhoto(*conv, convModel_->owner, QSize(110, 110))));
[invitationAvatar setImage:image];
}
[self updateInvitationView: conv];
}
- (void)updateInvitationView:(const lrc::api::conversation::Info*) conversation {
self.isRequest = conversation->isRequest;
NSString* bestName = bestNameForConversation(*conversation, *convModel_);
bool showInvitationView = conversation->isRequest || (convModel_->owner.profileInfo.type == lrc::api::profile::Type::JAMI && conversation->interactions.size() == 0);
invitationView.hidden = !showInvitationView;
invitationBlock.enabled = !conversation->needsSyncing && conversation->isRequest;
invitationRefuse.enabled = !conversation->needsSyncing && conversation->isRequest;
invitationAccept.enabled = !conversation->needsSyncing && conversation->isRequest;
invitationControls.hidden = conversation->needsSyncing || !conversation->isRequest;
invitationLabel.hidden = conversation->needsSyncing || !conversation->isRequest;
invitationMessage.hidden = conversation->isRequest && !conversation->needsSyncing;
if (!showInvitationView) {
return;
}
if (conversation->isRequest && conversation->needsSyncing) {
NSString *syncTitle = [NSString stringWithFormat:
NSLocalizedString(@"We are waiting for %@ connects to synchronize the conversation.",@"Synchronization label for conversation {Name}"),
bestName];
invitationMessage.stringValue = syncTitle;
NSString *waitSync = NSLocalizedString(@"You have accepted the conversation request.", @"Synchronization explanation label");
[self setInvitationText: waitSync];
} else if (conversation->isRequest) {
NSString *invitationReceived = NSLocalizedString(@"Hello, \nWould you like to join the conversation?", @"Incoming conversation request title");
[self setInvitationText: invitationReceived];
} else {
NSString *sendInvitationText1 = NSLocalizedString(@"Send him/her a contact request to be able to exchange together.", @"Send request explanation");
invitationMessage.stringValue = sendInvitationText1;
NSString *sendInvitationText = [NSString stringWithFormat:
NSLocalizedString(@"%@ is not in your contacts.", @"Send request to {Name}"),
bestName];
[self setInvitationText: sendInvitationText];
}
}
- (void) initFrame
......@@ -328,4 +431,16 @@ NSInteger const SEND_PANEL_MAX_HEIGHT = 120;
[leaveMessageConversations removeObject:convUid_.toNSString()];
}
- (IBAction) acceptInvitation:(id)sender {
convModel_->makePermanent(convUid_);
}
- (IBAction) refuseInvitation:(id)sender {
convModel_->removeConversation(convUid_);
}
- (IBAction) blockInvitation:(id)sender {
convModel_->removeConversation(convUid_, true);
}
@end
......@@ -42,7 +42,6 @@
* if message.length is > 0, button is enabled, otherwise disabled
*/
@property (retain) NSString* message;
/**
* This is a KVO method to bind the pending files collection view visibility
*/
......@@ -52,6 +51,7 @@
* This is a KVO method to bind the enable state of send button
*/
@property BOOL enableSendButton;
@property (nonatomic, weak) NSView* containerView;
-(void) setAVModel: (lrc::api::AVModel*) avmodel;
-(void) checkIfcomposingMsg;
......
......@@ -86,9 +86,6 @@ NSInteger const TOTALMSGS_TAG = 600;
NSInteger const TOTALINVITES_TAG = 700;
NSInteger const DATE_TAG = 800;
NSInteger const SNIPPET_TAG = 900;
NSInteger const ADD_BUTTON_TAG = 1000;
NSInteger const REFUSE_BUTTON_TAG = 1100;
NSInteger const BLOCK_BUTTON_TAG = 1200;
// Segment indices for smartlist selector
NSInteger const CONVERSATION_SEG = 0;
......@@ -551,25 +548,9 @@ NSInteger const REQUEST_SEG = 1;
NSLog(@"contact out of range");
}
NSButton* addContactButton = [result viewWithTag:ADD_BUTTON_TAG];
NSButton* refuseContactButton = [result viewWithTag:REFUSE_BUTTON_TAG];
NSButton* blockContactButton = [result viewWithTag:BLOCK_BUTTON_TAG];
[addContactButton setHidden:YES];
[refuseContactButton setHidden:YES];
[blockContactButton setHidden:YES];
if (profileType(conversation, *convModel_) == lrc::api::profile::Type::PENDING) {
if (conversation.isRequest) {
[lastInteractionDate setHidden:true];
[interactionSnippet setHidden:true];
[addContactButton setHidden:NO];
[refuseContactButton setHidden:NO];
[blockContactButton setHidden:NO];
[addContactButton setAction:@selector(acceptInvitation:)];
[addContactButton setTarget:self];
[refuseContactButton setAction:@selector(refuseInvitation:)];
[refuseContactButton setTarget:self];
[blockContactButton setAction:@selector(blockPendingContact:)];
[blockContactButton setTarget:self];
return result;
}
......@@ -699,14 +680,11 @@ NSInteger const REQUEST_SEG = 1;
if (!convOpt.has_value())
return;
lrc::api::conversation::Info& conversation = *convOpt;
@try {
auto contact = convModel_->owner.contactModel->getContact(conversation.participants[0]);
if (!contact.profileInfo.uri.isEmpty() && contact.profileInfo.uri.compare(selectedUid_) == 0) {
if (conversation.participants.size() > 0) {
if (conversation.participants[0] == selectedUid_) {
selectedUid_ = uid;
convModel_->selectConversation(uid);
}
} @catch (NSException *exception) {
return;
}
}
......@@ -746,7 +724,7 @@ NSInteger const REQUEST_SEG = 1;
if (selectedUid_ == uid) {
return YES;
}
@try {
try {
auto contact = convModel_->owner.contactModel->getContact(conversation.participants[0]);
if ((contact.profileInfo.uri.isEmpty() && contact.profileInfo.type != lrc::api::profile::Type::SIP) || contact.profileInfo.type == lrc::api::profile::Type::INVALID) {
return YES;
......@@ -755,7 +733,7 @@ NSInteger const REQUEST_SEG = 1;
convModel_->selectConversation(uid);
[self.view.window makeFirstResponder: smartView];
return YES;
} @catch (NSException *exception) {
} catch (std::out_of_range& e) {
return YES;
}
}
......@@ -811,7 +789,7 @@ NSInteger const REQUEST_SEG = 1;
return nil;
lrc::api::conversation::Info& conversation = *convOpt;
@try {
try {
auto contact = convModel_->owner.contactModel->getContact(conversation.participants[0]);
if (contact.profileInfo.type == lrc::api::profile::Type::INVALID) {
return nil;
......@@ -876,7 +854,7 @@ NSInteger const REQUEST_SEG = 1;
}
return theMenu;
}
@catch (NSException *exception) {
catch (std::out_of_range& e) {
return nil;
}
}
......
......@@ -58,3 +58,12 @@
/* Class = "CocoaBindingsConnection"; ibShadowedIsNilPlaceholder = "Type a message"; ObjectID = "rQj-9q-WQ6"; */
"rQj-9q-WQ6.ibShadowedIsNilPlaceholder" = "Type a message";
/* Class = "NSButtonCell"; title = "BLOCK"; ObjectID = "HSp-y7-w6n"; */
"HSp-y7-w6n.title" = "BLOCK";
/* Class = "NSButtonCell"; title = "REFUSE"; ObjectID = "pIg-Hr-SJn"; */
"pIg-Hr-SJn.title" = "REFUSE";
/* Class = "NSButtonCell"; title = "ACCEPT"; ObjectID = "xiC-2C-Zf4"; */
"xiC-2C-Zf4.title" = "ACCEPT";
......@@ -10,8 +10,16 @@
<outlet property="addContactButton" destination="pGK-hO-X1Y" id="YeP-Gd-x6e"/>
<outlet property="conversationID" destination="SQT-Vf-Lhr" id="eab-vD-7X7"/>
<outlet property="conversationTitle" destination="ucx-6g-eJw" id="40T-pM-nix"/>
<outlet property="loadingindicator" destination="jf4-9g-QVb" id="pGV-oY-KTG"/>
<outlet property="loadingindicatorContainer" destination="a2B-6B-Ge1" id="msM-JI-qUj"/>
<outlet property="invitationAccept" destination="xiC-2C-Zf4" id="k8Z-DQ-05f"/>
<outlet property="invitationAvatar" destination="ngh-ta-KUT" id="gXh-h3-hiH"/>
<outlet property="invitationBlock" destination="HSp-y7-w6n" id="k9O-A0-5CG"/>
<outlet property="invitationBox" destination="R7t-h2-gHg" id="EZN-6w-Vfo"/>
<outlet property="invitationControls" destination="dI7-jW-4yK" id="DnP-Bz-v2R"/>
<outlet property="invitationLabel" destination="MLE-SS-L4Z" id="cLg-5U-XdW"/>
<outlet property="invitationMessage" destination="MH5-en-s0S" id="fnb-py-8BC"/>
<outlet property="invitationRefuse" destination="pIg-Hr-SJn" id="eR8-WY-2Ih"/>
<outlet property="invitationTitle" destination="SXe-zc-dGw" id="keh-U3-wiE"/>
<outlet property="invitationView" destination="a2B-6B-Ge1" id="Ojs-mq-eKP"/>
<outlet property="messagesViewVC" destination="iH6-17-JsM" id="uxH-Ra-lSr"/>
<outlet property="pluginButton" destination="FvO-Yj-ry0" id="35Y-R2-Gwa"/>
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
......@@ -35,12 +43,12 @@
<rect key="frame" x="0.0" y="145" width="838" height="466"/>
<subviews>
<scrollView verticalCompressionResistancePriority="250" borderType="none" autohidesScrollers="YES" horizontalLineScroll="90" horizontalPageScroll="10" verticalLineScroll="90" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" scrollerKnobStyle="dark" translatesAutoresizingMaskIntoConstraints="NO" id="Ez2-Rf-DZN">
<rect key="frame" x="69" y="0.0" width="700" height="466"/>
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" copiesOnScroll="NO" id="ofC-Bs-tHR">
<rect key="frame" x="49" y="0.0" width="700" height="466"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="ofC-Bs-tHR">
<rect key="frame" x="0.0" y="0.0" width="700" height="466"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" ambiguous="YES" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="none" autosaveColumns="NO" rowHeight="88" rowSizeStyle="automatic" usesAutomaticRowHeights="YES" viewBased="YES" id="bOO-CW-S21">
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="none" autosaveColumns="NO" rowHeight="88" rowSizeStyle="automatic" usesAutomaticRowHeights="YES" viewBased="YES" id="bOO-CW-S21">
<rect key="frame" x="0.0" y="0.0" width="700" height="466"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
......@@ -765,6 +773,7 @@
<constraint firstItem="w4b-RA-Kx1" firstAttribute="leading" secondItem="dIr-5S-yPG" secondAttribute="leading" constant="20" id="DSU-4w-c1E"/>
<constraint firstAttribute="trailing" secondItem="w4b-RA-Kx1" secondAttribute="trailing" constant="20" id="tcv-4m-YWP"/>
</constraints>
<<<<<<< HEAD
<visibilityPriorities>
<integer value="1000"/>
<integer value="1000"/>
......@@ -776,6 +785,12 @@
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
=======
<connections>
<binding destination="-2" name="hidden" keyPath="isRequest" id="2Xv-I0-yS8"/>
</connections>
</customView>
>>>>>>> 44a652f3 (swarm: add invitation view)
<stackView distribution="fill" orientation="vertical" alignment="leading" spacing="4" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mor-Vl-Fr5">
<rect key="frame" x="55" y="621" width="50" height="36"/>
<subviews>
......@@ -837,6 +852,11 @@
</userDefinedRuntimeAttributes>
<connections>
<action selector="addContact:" target="-2" id="9DI-Pm-X0I"/>
<binding destination="-2" name="enabled" keyPath="isRequest" id="SHj-6k-6zi">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
</connections>
</button>
<button toolTip="Start audio call" verticalHuggingPriority="750" tag="400" translatesAutoresizingMaskIntoConstraints="NO" id="RuH-fO-poy" userLabel="Audio Call Button" customClass="HoverButton">
......@@ -868,6 +888,11 @@
</userDefinedRuntimeAttributes>
<connections>
<action selector="placeAudioCall:" target="-2" id="ycm-jI-2M5"/>
<binding destination="-2" name="enabled" keyPath="isRequest" id="PcW-uz-duF">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
</connections>
</button>
<button toolTip="Start video call" verticalHuggingPriority="750" tag="400" translatesAutoresizingMaskIntoConstraints="NO" id="cFH-d7-Erh" userLabel="Call Button" customClass="HoverButton">
......@@ -899,6 +924,11 @@
</userDefinedRuntimeAttributes>
<connections>
<action selector="placeCall:" target="-2" id="2h9-fM-gof"/>
<binding destination="-2" name="enabled" keyPath="isRequest" id="H1M-2S-SI1">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
</connections>
</button>
<button toolTip="edit plugins" verticalHuggingPriority="750" tag="400" translatesAutoresizingMaskIntoConstraints="NO" id="FvO-Yj-ry0" userLabel="Plugin Button" customClass="HoverButton">
......@@ -948,51 +978,187 @@
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
<connections>
<binding destination="-2" name="hidden" keyPath="isRequest" id="R3t-4E-frd"/>
</connections>
</stackView>
<customView hidden="YES" translatesAutoresizingMaskIntoConstraints="NO" id="a2B-6B-Ge1">
<rect key="frame" x="299" y="251" width="200" height="80"/>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="a2B-6B-Ge1">
<rect key="frame" x="0.0" y="60" width="798" height="465"/>
<subviews>
<stackView distribution="fill" orientation="vertical" alignment="centerX" spacing="10" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ux8-7c-iqB">
<rect key="frame" x="35" y="12" width="130" height="56"/>
<stackView distribution="fill" orientation="vertical" alignment="centerX" spacing="20" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ux8-7c-iqB">
<rect key="frame" x="0.0" y="45" width="798" height="420"/>
<subviews>
<progressIndicator wantsLayer="YES" maxValue="100" indeterminate="YES" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="jf4-9g-QVb">
<rect key="frame" x="50" y="26" width="30" height="30"/>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Br2-RC-CZa">
<rect key="frame" x="389" y="390" width="20" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="30" id="FtR-se-7Fd"/>
<constraint firstAttribute="height" constant="30" id="cWd-oz-BGI"/>
<constraint firstAttribute="height" constant="30" id="7NN-cJ-oGk"/>
<constraint firstAttribute="width" constant="20" id="MMF-jO-XhO"/>
</constraints>
</progressIndicator>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3HL-Cv-WFO">
<rect key="frame" x="-2" y="0.0" width="134" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Loading conversation" id="mfD-q3-nnf">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
</customView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MLE-SS-L4Z">
<rect key="frame" x="260" y="353" width="278" height="17"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="has sent you a request for a conversation." id="oIX-py-QDN">
<font key="font" metaFont="system" size="14"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="nK6-oq-3pS">
<rect key="frame" x="389" y="328" width="20" height="5"/>
<constraints>
<constraint firstAttribute="height" constant="5" id="aWj-j0-eOs"/>
<constraint firstAttribute="width" constant="20" id="eAu-8u-0jf"/>
</constraints>
</customView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="ADD-7y-WcE">
<rect key="frame" x="197" y="40" width="405" height="268"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="R7t-h2-gHg">
<rect key="frame" x="15" y="15" width="375" height="198"/>
<subviews>
<stackView distribution="fill" orientation="vertical" alignment="centerX" spacing="20" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vYd-fa-9HP">
<rect key="frame" x="50" y="40" width="275" height="63"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="SXe-zc-dGw">
<rect key="frame" x="-2" y="0.0" width="279" height="63"/>
<textFieldCell key="cell" enabled="NO" alignment="center" id="CsY-gl-KjZ">
<font key="font" metaFont="system" size="18"/>
<string key="title">Hello,
Would you like to join the conversation?</string>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField hidden="YES" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="MH5-en-s0S">
<rect key="frame" x="-2" y="46" width="102" height="17"/>
<textFieldCell key="cell" selectable="YES" alignment="center" title="Multiline Label" id="8ZQ-pO-oxM">
<font key="font" metaFont="system" size="14"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<visibilityPriorities>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="vYd-fa-9HP" secondAttribute="bottom" constant="40" id="7HQ-nm-J6V"/>
<constraint firstItem="vYd-fa-9HP" firstAttribute="centerX" secondItem="R7t-h2-gHg" secondAttribute="centerX" id="Fnt-dT-O5x"/>
<constraint firstItem="vYd-fa-9HP" firstAttribute="leading" secondItem="R7t-h2-gHg" secondAttribute="leading" constant="50" id="lqT-YU-1Ni"/>
</constraints>
</customView>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ngh-ta-KUT">
<rect key="frame" x="147" y="158" width="110" height="110"/>
<constraints>
<constraint firstAttribute="height" constant="110" id="atY-3l-T8X"/>
<constraint firstAttribute="width" constant="110" id="tiP-f3-z6y"/>
</constraints>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="d7s-gO-wzd"/>
</imageView>
</subviews>
<constraints>
<constraint firstItem="ngh-ta-KUT" firstAttribute="top" secondItem="ADD-7y-WcE" secondAttribute="top" id="7yv-7S-tb5"/>
<constraint firstAttribute="trailing" secondItem="R7t-h2-gHg" secondAttribute="trailing" constant="15" id="8KL-y6-tgS"/>
<constraint firstItem="R7t-h2-gHg" firstAttribute="top" secondItem="ngh-ta-KUT" secondAttribute="bottom" constant="-55" id="Hht-y6-rey"/>
<constraint firstAttribute="bottom" secondItem="R7t-h2-gHg" secondAttribute="bottom" constant="15" id="Iv3-B5-uQZ"/>
<constraint firstAttribute="width" constant="405" id="M5G-xD-sAn"/>
<constraint firstItem="ngh-ta-KUT" firstAttribute="centerX" secondItem="ADD-7y-WcE" secondAttribute="centerX" id="Vpr-f8-Gym"/>
<constraint firstItem="vYd-fa-9HP" firstAttribute="top" secondItem="ngh-ta-KUT" secondAttribute="bottom" constant="40" id="ck4-mi-fDZ"/>
<constraint firstItem="R7t-h2-gHg" firstAttribute="leading" secondItem="ADD-7y-WcE" secondAttribute="leading" constant="15" id="rNo-Rd-UUA"/>
</constraints>
</customView>
<stackView distribution="fill" orientation="horizontal" alignment="centerY" spacing="40" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dI7-jW-4yK">
<rect key="frame" x="279" y="0.0" width="241" height="20"/>
<subviews>
<button verticalHuggingPriority="750" id="HSp-y7-w6n">
<rect key="frame" x="20" y="-91" width="27" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="inline" title="BLOCK" bezelStyle="inline" image="buttonCell:zlf-wu-PaQ:image" alignment="center" imageScaling="proportionallyDown" inset="2" id="zlf-wu-PaQ">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="systemSemibold" size="12"/>
</buttonCell>
<color key="contentTintColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<connections>
<action selector="blockInvitation:" target="-2" id="WrA-Va-TVO"/>
</connections>
</button>
<button verticalHuggingPriority="750" id="pIg-Hr-SJn" userLabel="REFUSE">
<rect key="frame" x="113" y="-91" width="27" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="inline" title="REFUSE" bezelStyle="inline" image="buttonCell:Jed-Ij-EeH:image" alignment="center" imageScaling="proportionallyDown" inset="2" id="Jed-Ij-EeH">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="systemSemibold" size="12"/>
</buttonCell>
<color key="contentTintColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<connections>
<action selector="refuseInvitation:" target="-2" id="Tnc-Gv-KUe"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xiC-2C-Zf4">
<rect key="frame" x="180" y="-90" width="61" height="15"/>
<buttonCell key="cell" type="inline" title="ACCEPT" bezelStyle="inline" alignment="center" imageScaling="proportionallyDown" inset="2" id="TX1-ru-1zT">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="systemSemibold" size="12"/>
</buttonCell>
<color key="contentTintColor" red="0.043137254901960784" green="0.50980392156862742" blue="0.44313725490196076" alpha="0.84999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<action selector="acceptInvitation:" target="-2" id="Pqs-nw-Ljr"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="height" constant="20" id="Fvc-cU-AjH"/>
<constraint firstItem="pIg-Hr-SJn" firstAttribute="centerY" secondItem="HSp-y7-w6n" secondAttribute="centerY" id="PDA-Lg-ttc"/>
<constraint firstItem="xiC-2C-Zf4" firstAttribute="centerY" secondItem="HSp-y7-w6n" secondAttribute="centerY" id="feU-ED-BkL"/>
</constraints>
<visibilityPriorities>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
</subviews>
<visibilityPriorities>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
</subviews>
<constraints>
<constraint firstAttribute="height" constant="80" id="UyJ-03-RLP"/>
<constraint firstItem="ux8-7c-iqB" firstAttribute="centerX" secondItem="a2B-6B-Ge1" secondAttribute="centerX" id="fIA-5F-V8l"/>
<constraint firstItem="ux8-7c-iqB" firstAttribute="centerY" secondItem="a2B-6B-Ge1" secondAttribute="centerY" id="o1A-cu-d8A"/>
<constraint firstAttribute="width" constant="200" id="yiD-Tf-FpX"/>