Commit d51a3252 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk Committed by Andreas Traczyk

smart list: add contextual menu

Add next options for contacts in smart list:
- video call
- audio call
- clear conversation
- block contact
- add contact

Change-Id: I9e668f0cc0848d35e0aad31d0efd16d94a78d916
Reviewed-by: Andreas Traczyk's avatarAndreas Traczyk <andreas.traczyk@savoirfairelinux.com>
parent 1004caa8
......@@ -48,6 +48,7 @@
QMetaObject::Connection modelSortedSignal_;
QMetaObject::Connection filterChangedSignal_;
QMetaObject::Connection interactionStatusUpdatedSignal_;
QMetaObject::Connection conversationClearedSignal;
}
@property (nonatomic, strong, readonly) INDSequentialTextSelectionManager* selectionManager;
......@@ -89,6 +90,7 @@ NSInteger const GENERIC_INT_TEXT_TAG = 100;
// Signal triggered when messages are received or their status updated
QObject::disconnect(newInteractionSignal_);
QObject::disconnect(interactionStatusUpdatedSignal_);
QObject::disconnect(conversationClearedSignal);
newInteractionSignal_ = QObject::connect(convModel_, &lrc::api::ConversationModel::newInteraction,
[self](const std::string& uid, uint64_t interactionId, const lrc::api::interaction::Info& interaction){
if (uid != convUid_)
......@@ -105,6 +107,12 @@ NSInteger const GENERIC_INT_TEXT_TAG = 100;
[conversationView reloadData];
[conversationView scrollToEndOfDocument:nil];
});
conversationClearedSignal = QObject::connect(convModel_, &lrc::api::ConversationModel::conversationCleared,
[self](){
cachedConv_ = nil;
[conversationView reloadData];
[conversationView scrollToEndOfDocument:nil];
});
// Signals tracking changes in conversation list, we need them as cached conversation can be invalid
// after a reordering.
......
......@@ -56,7 +56,7 @@
__strong IBOutlet NSSegmentedControl *listTypeSelector;
bool selectorIsPresent;
QMetaObject::Connection modelSortedConnection_, filterChangedConnection_, newConversationConnection_, conversationRemovedConnection_, interactionStatusUpdatedConnection_;
QMetaObject::Connection modelSortedConnection_, filterChangedConnection_, newConversationConnection_, conversationRemovedConnection_, interactionStatusUpdatedConnection_, conversationClearedConnection;
NSTimer* statusUpdateDebounceTimer;
lrc::api::ConversationModel* model_;
......@@ -176,6 +176,7 @@ NSInteger const REQUEST_SEG = 1;
[smartView scrollToBeginningOfDocument:nil];
}
- (BOOL)setConversationModel:(lrc::api::ConversationModel *)conversationModel
{
if (model_ != conversationModel) {
......@@ -186,6 +187,7 @@ NSInteger const REQUEST_SEG = 1;
QObject::disconnect(newConversationConnection_);
QObject::disconnect(conversationRemovedConnection_);
QObject::disconnect(interactionStatusUpdatedConnection_);
QObject::disconnect(conversationClearedConnection);
[self reloadData];
if (model_ != nil) {
modelSortedConnection_ = QObject::connect(model_, &lrc::api::ConversationModel::modelSorted,
......@@ -204,6 +206,11 @@ NSInteger const REQUEST_SEG = 1;
[self] (){
[self reloadData];
});
conversationClearedConnection = QObject::connect(model_, &lrc::api::ConversationModel::conversationCleared,
[self] (const std::string& id){
[self deselect];
[delegate listTypeChanged];
});
interactionStatusUpdatedConnection_ = QObject::connect(model_, &lrc::api::ConversationModel::interactionStatusUpdated,
[self] (const std::string& convUid) {
if (convUid != selectedUid_)
......@@ -516,73 +523,130 @@ NSInteger const REQUEST_SEG = 1;
#pragma mark - ContextMenuDelegate
#if 0
// TODO: Reimplement contextual menu with new models and behaviors
- (NSMenu*) contextualMenuForIndex:(NSTreeNode*) item
- (NSMenu*) contextualMenuForRow:(int) index
{
auto qIdx = [treeController toQIdx:item];
if (!qIdx.isValid()) {
return nil;
}
auto originIdx = RecentModel::instance().peopleProxy()->mapToSource(qIdx);
auto contactmethods = RecentModel::instance().getContactMethods(originIdx);
if (contactmethods.isEmpty())
if (model_ == nil)
return nil;
NSMenu *theMenu = [[NSMenu alloc] initWithTitle:@""];
auto conversation = model_->filteredConversation(NSInteger(index));
if (contactmethods.size() == 1
&& !contactmethods.first()->contact()
|| contactmethods.first()->contact()->isPlaceHolder()) {
@try {
auto contact = model_->owner.contactModel->getContact(conversation.participants[0]);
if (contact.profileInfo.type == lrc::api::profile::Type::INVALID) {
return nil;
}
NSMenuItem* addContactItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Add to contacts", @"Contextual menu action")
action:@selector(addContactForRow:)
keyEquivalent:@""];
[addContactItem setRepresentedObject:item];
[theMenu addItem:addContactItem];
} else if (auto person = contactmethods.first()->contact()) {
NSMenuItem* copyNameItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Copy name", @"Contextual menu action")
action:@selector(copyStringToPasteboard:)
keyEquivalent:@""];
BOOL isSIP = false;
BOOL isRingContact = false;
/* for SIP contact show only call menu options
* if contact does not have uri that is not RING contact
* for trusted Ring contact show option block contact
* for untrasted contact show option add contact
*/
if (contact.profileInfo.type == lrc::api::profile::Type::SIP) {
isSIP = true;
} else if (contact.profileInfo.uri.empty()) {
return nil;
}
[copyNameItem setRepresentedObject:person->formattedName().toNSString()];
[theMenu addItem:copyNameItem];
else if (contact.profileInfo.type == lrc::api::profile::Type::RING && contact.isTrusted == true) {
isRingContact = true;
}
auto conversationUD = conversation.uid;
NSMenu *theMenu = [[NSMenu alloc] initWithTitle:@""];
NSString* conversationUID = @(conversationUD.c_str());
NSMenuItem* separator = [NSMenuItem separatorItem];
NSMenuItem* videoCallItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Place video call",
@"Contextual menu action")
action:@selector(videoCall:)
keyEquivalent:@""];
NSMenuItem* audioCallItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Place audio call",
@"Contextual menu action")
action:@selector(audioCall:)
keyEquivalent:@""];
[videoCallItem setRepresentedObject: conversationUID];
[audioCallItem setRepresentedObject: conversationUID];
[theMenu addItem:videoCallItem];
[theMenu addItem:audioCallItem];
if (isSIP == false) {
[theMenu addItem:separator];
NSMenuItem* clearConversationItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Clear conversation", @"Contextual menu action")
action:@selector(clearConversation:)
keyEquivalent:@""];
[clearConversationItem setRepresentedObject: conversationUID];
[theMenu addItem:clearConversationItem];
if(isRingContact) {
NSMenuItem* blockContactItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Block contact", @"Contextual menu action")
action:@selector(blockContact:)
keyEquivalent:@""];
[blockContactItem setRepresentedObject: conversationUID];
[theMenu addItem:blockContactItem];
} else {
NSMenuItem* addContactItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Add to contacts", @"Contextual menu action")
action:@selector(addContact:)
keyEquivalent:@"A"];
[addContactItem setRepresentedObject: conversationUID];
[theMenu addItem:addContactItem];
}
}
return theMenu;
}
@catch (NSException *exception) {
return nil;
}
}
NSMenu* copySubmenu = [[NSMenu alloc] init];
NSMenu* callSubmenu = [[NSMenu alloc] init];
for (auto cm : contactmethods) {
NSMenuItem* tmpCopyItem = [[NSMenuItem alloc] initWithTitle:cm->uri().toNSString()
action:@selector(copyStringToPasteboard:)
keyEquivalent:@""];
[tmpCopyItem setRepresentedObject:cm->uri().toNSString()];
[copySubmenu addItem:tmpCopyItem];
- (void) addContact: (NSMenuItem* ) item {
auto menuObject = item.representedObject;
if(menuObject == nil) {
return;
}
NSString * convUId = (NSString*)menuObject;
std::string conversationID = std::string([convUId UTF8String]);
model_->makePermanent(conversationID);
}
NSMenuItem* tmpCallItem = [[NSMenuItem alloc] initWithTitle:cm->uri().toNSString()
action:@selector(callNumber:)
keyEquivalent:@""];
[tmpCallItem setRepresentedObject:cm->uri().toNSString()];
[callSubmenu addItem:tmpCallItem];
- (void) blockContact: (NSMenuItem* ) item {
auto menuObject = item.representedObject;
if(menuObject == nil) {
return;
}
NSString * convUId = (NSString*)menuObject;
std::string conversationID = std::string([convUId UTF8String]);
model_->clearHistory(conversationID);
model_->removeConversation(conversationID, true);
}
NSMenuItem* copyNumberItem = [[NSMenuItem alloc] init];
[copyNumberItem setTitle:NSLocalizedString(@"Copy number", @"Contextual menu action")];
[copyNumberItem setSubmenu:copySubmenu];
- (void) audioCall: (NSMenuItem* ) item {
auto menuObject = item.representedObject;
if(menuObject == nil) {
return;
}
NSString * convUId = (NSString*)menuObject;
std::string conversationID = std::string([convUId UTF8String]);
model_->placeAudioOnlyCall(conversationID);
NSMenuItem* callItems = [[NSMenuItem alloc] init];
[callItems setTitle:NSLocalizedString(@"Call number", @"Contextual menu action")];
[callItems setSubmenu:callSubmenu];
}
[theMenu insertItem:copyNumberItem atIndex:theMenu.itemArray.count];
[theMenu insertItem:[NSMenuItem separatorItem] atIndex:theMenu.itemArray.count];
[theMenu insertItem:callItems atIndex:theMenu.itemArray.count];
- (void) videoCall: (NSMenuItem* ) item {
auto menuObject = item.representedObject;
if(menuObject == nil) {
return;
}
NSString * convUId = (NSString*)menuObject;
std::string conversationID = std::string([convUId UTF8String]);
model_->placeCall(conversationID);
}
return theMenu;
- (void) clearConversation:(NSMenuItem* ) item {
auto menuObject = item.representedObject;
if(menuObject == nil) {
return;
}
NSString * convUId = (NSString*)menuObject;
std::string conversationID = std::string([convUId UTF8String]);
model_->clearHistory(conversationID);
}
#endif
@end
......@@ -24,7 +24,7 @@
@required
- (NSMenu*) contextualMenuForIndex:(NSTreeNode*) path;
- (NSMenu*) contextualMenuForRow:(int) index;
@end
......
......@@ -26,11 +26,11 @@
- (NSMenu*)menuForEvent:(NSEvent*)evt
{
// TODO : Reimplement without outlineView itemAtRow: method
// NSPoint pt = [self convertPoint:[evt locationInWindow] fromView:nil];
// int rowIdx = [self rowAtPoint:pt];
// if (self.contextMenuDelegate && rowIdx >= 0) {
// return [self.contextMenuDelegate contextualMenuForIndex:[self itemAtRow:rowIdx]];
// }
NSPoint pt = [self convertPoint:[evt locationInWindow] fromView:nil];
int rowIdx = [self rowAtPoint:pt];
if (self.contextMenuDelegate && rowIdx >= 0) {
return [self.contextMenuDelegate contextualMenuForRow:rowIdx];
}
return nil;
}
......
......@@ -7,6 +7,18 @@
/* Contextual menu action */
"Add to contacts" = "Add to contacts";
/* Contextual menu action */
"Place video call" = "Place video call";
/* Contextual menu action */
"Place audio call" = "Place audio call";
/* Contextual menu action */
"Clear conversation" = "Clear conversation";
/* Contextual menu action */
"Block contact" = "Block contact";
/* Text shown to the user */
"Alias : " = "Alias : ";
......
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