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

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";
This diff is collapsed.
......@@ -304,3 +304,26 @@
/* share button tooltip */
"Share" = "Share";
/* Synchronization label for conversation {Name} */
"We are waiting for %@ connects to synchronize the conversation." = "We are waiting for %@ connects to synchronize the conversation.";
/* Incoming conversation request title */
"Hello, \nWould you like to join the conversation?" = "Hello, \nWould you like to join the conversation?";
/* Invitation request from {Name} */
"%@ has sent you a request for a conversation." = "%@ has sent you a request for a conversation.";
/* Synchronization explanation label */
"You have accepted the conversation request." = "You have accepted the conversation request.";
/* Send request to {Name} */
"%@ is not in your contacts." = "%@ is not in your contacts.";
/* Send request explanation */
"Send him/her a contact request to be able to exchange together." = "Send him/her a contact request to be able to exchange together.";
/* Wait for request acceptance from {Name} */
"%@ has not yet accepted your contact request." = "%@ has not yet accepted your contact request.";
/* Wait for request acceptance from {Name} explanation */
"%@ must accept your contact request to answer you." = "%@ must accept your contact request to answer you.";
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment