blob: 6f51a2cf95888459c37e846a2393db02ff18e29c [file] [log] [blame]
Olivier Soldanod4311552017-11-20 15:09:53 -05001/*
Sébastien Blin029ffa82019-01-02 17:43:48 -05002 * Copyright (C) 2017-2019 Savoir-faire Linux Inc.
Olivier Soldanod4311552017-11-20 15:09:53 -05003 * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
Andreas Traczyk77a50d52018-05-08 17:47:31 -040020#import <map>
21
Olivier Soldanod4311552017-11-20 15:09:53 -050022#import <Foundation/Foundation.h>
Andreas Traczyk252a94a2018-04-20 16:36:20 -040023#import "NSString+Extensions.h"
Kateryna Kostiuk9fca5422018-11-19 16:27:46 -050024#import "views/NSColor+RingTheme.h"
25
Andreas Traczyk77a50d52018-05-08 17:47:31 -040026
27// new lrc
Olivier Soldanod4311552017-11-20 15:09:53 -050028#import <api/conversation.h>
29#import <api/conversationmodel.h>
30#import <api/account.h>
31#import <api/contactmodel.h>
32#import <api/contact.h>
Andreas Traczyk77a50d52018-05-08 17:47:31 -040033
Kateryna Kostiuk0c0801e2019-07-18 20:10:51 -040034//Qt
35#import <QtCore/QDir>
36#import <qapplication.h>
37
Olivier Soldanod4311552017-11-20 15:09:53 -050038static inline NSString* bestIDForConversation(const lrc::api::conversation::Info& conv, const lrc::api::ConversationModel& model)
39{
Andreas Traczyk4e39aa52018-05-11 17:29:26 -040040 try {
41 auto contact = model.owner.contactModel->getContact(conv.participants[0]);
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040042 auto name = contact.registeredName.trimmed().replace("\r","").replace("\n","");
43 if (!name.isEmpty()) {
44 return [name.toNSString() removeEmptyLinesAtBorders];
Andreas Traczyk4e39aa52018-05-11 17:29:26 -040045 }
46 else {
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040047 return [contact.profileInfo.uri.trimmed().replace("\r","").replace("\n","").toNSString() removeEmptyLinesAtBorders];
Andreas Traczyk4e39aa52018-05-11 17:29:26 -040048 }
49 } catch (std::out_of_range& e) {
50 NSLog(@"bestIDForConversation: getContact - out of range");
Kateryna Kostiuk4c703872018-12-28 17:29:05 -050051 return @"";
Andreas Traczyk252a94a2018-04-20 16:36:20 -040052 }
Olivier Soldanod4311552017-11-20 15:09:53 -050053}
54
Kateryna Kostiukd73f9602018-07-24 13:51:28 -040055static inline NSString* bestIDForAccount(const lrc::api::account::Info& account)
56{
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040057 auto name = account.registeredName.trimmed().replace("\r","").replace("\n","");
58 if (!name.isEmpty()) {
59 return [name.toNSString() removeEmptyLinesAtBorders];
Kateryna Kostiukd73f9602018-07-24 13:51:28 -040060 }
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040061 return [account.profileInfo.uri.trimmed().replace("\r","").replace("\n","").toNSString() removeEmptyLinesAtBorders];
Kateryna Kostiukd73f9602018-07-24 13:51:28 -040062}
63
64static inline NSString* bestNameForAccount(const lrc::api::account::Info& account)
65{
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040066 if (account.profileInfo.alias.isEmpty()) {
Kateryna Kostiukd73f9602018-07-24 13:51:28 -040067 return bestIDForAccount(account);
68 }
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040069 return account.profileInfo.alias.toNSString();
Kateryna Kostiukd73f9602018-07-24 13:51:28 -040070}
71
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040072static inline NSString* bestIDForContact(const lrc::api::contact::Info& contact)
73{
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040074 auto name = contact.registeredName.trimmed().replace("\r","").replace("\n","");
75 if (!name.isEmpty()) {
76 return [name.toNSString() removeEmptyLinesAtBorders];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040077 }
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040078 return [contact.profileInfo.uri.trimmed().replace("\r","").replace("\n","").toNSString() removeEmptyLinesAtBorders];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040079}
80
81static inline NSString* bestNameForContact(const lrc::api::contact::Info& contact)
82{
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040083 if (contact.profileInfo.alias.isEmpty()) {
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040084 return bestIDForContact(contact);
85 }
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040086 return contact.profileInfo.alias.toNSString();
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040087}
88
Olivier Soldanod4311552017-11-20 15:09:53 -050089static inline NSString* bestNameForConversation(const lrc::api::conversation::Info& conv, const lrc::api::ConversationModel& model)
90{
Andreas Traczyk4e39aa52018-05-11 17:29:26 -040091 try {
92 auto contact = model.owner.contactModel->getContact(conv.participants[0]);
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040093 if (contact.profileInfo.alias.isEmpty()) {
Andreas Traczyk4e39aa52018-05-11 17:29:26 -040094 return bestIDForConversation(conv, model);
95 }
96 auto alias = contact.profileInfo.alias;
Andreas Traczyk4e39aa52018-05-11 17:29:26 -040097 if(alias.length() == 0) {
98 return bestIDForConversation(conv, model);
99 }
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400100 return [alias.toNSString() removeEmptyLinesAtBorders];
Andreas Traczyk4e39aa52018-05-11 17:29:26 -0400101 } catch (std::out_of_range& e) {
102 NSLog(@"bestNameForConversation: getContact - out of range");
Kateryna Kostiuk4c703872018-12-28 17:29:05 -0500103 return @"";
Andreas Traczyk252a94a2018-04-20 16:36:20 -0400104 }
Andreas Traczyk252a94a2018-04-20 16:36:20 -0400105}
106
Kateryna Kostiuk0c0801e2019-07-18 20:10:51 -0400107static inline NSString* defaultRingtonePath() {
108 QDir ringtonesDir(QCoreApplication::applicationDirPath());
109 ringtonesDir.cdUp();
110 ringtonesDir.cd("Resources/ringtones/");
111 return [ringtonesDir.path().toNSString() stringByAppendingString:@"/default.opus"];
112}
113
Andreas Traczyk252a94a2018-04-20 16:36:20 -0400114static inline lrc::api::profile::Type profileType(const lrc::api::conversation::Info& conv, const lrc::api::ConversationModel& model)
115{
116 @try {
117 auto contact = model.owner.contactModel->getContact(conv.participants[0]);
118 return contact.profileInfo.type;
119 }
120 @catch (NSException *exception) {
121 lrc::api::profile::Type::INVALID;
122 }
Olivier Soldanod4311552017-11-20 15:09:53 -0500123}
Anthony Léonard6f819752018-01-05 09:53:40 -0500124
125/**
Kateryna Kostiuka7b909c2020-10-19 11:46:26 -0400126 * This function return an optional reference to Conversation::Info in ConversationModel given its uid.
Anthony Léonard6f819752018-01-05 09:53:40 -0500127 * @param uid UID of conversation being searched
128 * @param model ConversationModel in which to do the lookup
Kateryna Kostiuka7b909c2020-10-19 11:46:26 -0400129 * @return an optional reference to Conversation::Info.
Anthony Léonard6f819752018-01-05 09:53:40 -0500130 */
Kateryna Kostiuka7b909c2020-10-19 11:46:26 -0400131static inline OptRef<lrc::api::conversation::Info> getConversationFromUid(const QString& uid, lrc::api::ConversationModel& model) {
132 return model.getConversationForUid(uid);
Kateryna Kostiuk3541ae22020-08-17 12:26:14 -0400133}
Kateryna Kostiuk3541ae22020-08-17 12:26:14 -0400134/**
Kateryna Kostiuka7b909c2020-10-19 11:46:26 -0400135 * This function return an optional reference to Conversation::Info in ConversationModel given its participant uri.
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500136 * @param uri URI of participant
137 * @param model ConversationModel in which to do the lookup
Kateryna Kostiuka7b909c2020-10-19 11:46:26 -0400138 * @return an optional reference to conversation::Info.
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500139 */
Kateryna Kostiuka7b909c2020-10-19 11:46:26 -0400140static inline OptRef<lrc::api::conversation::Info> getConversationFromURI(const QString& uri, lrc::api::ConversationModel& model) {
141 return model.getConversationForPeerUri(uri);
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500142}
Kateryna Kostiuka7b909c2020-10-19 11:46:26 -0400143/**
144 * This function return an optional reference to Conversation::Info in ConversationModel given its call Id
145 * @param callId callId for conversation
146 * @param model ConversationModel in which to do the lookup
147 * @return an optional reference to conversation::Info.
148 */
149static inline OptRef<lrc::api::conversation::Info> getConversationFromCallId(const QString& callId, lrc::api::ConversationModel& model) {
150 return model.getConversationForCallId(callId);
151}
152/**
153 * This function return an index of filtered conversation for given conversation uid. If no result found return -1
154 * @param uid UID of conversation being searched
155 * @param model ConversationModel in which to do the lookup
156 * @return an index of corresponding Conversation if any. Otherwise return -1.
157 */
158static inline int getFilteredConversationIndexFromUid(const QString& uid, const lrc::api::ConversationModel& model) {
159 auto it = std::find_if(model.allFilteredConversations().get().begin(), model.allFilteredConversations().get().end(),
160 [&] (const lrc::api::conversation::Info& conv) {
161 return uid == conv.uid;
162 });
163 if (it != model.allFilteredConversations().get().end()) {
164 return std::distance(model.allFilteredConversations().get().begin(), it);
165 }
166 return -1;
167}
168/**
169* This function return an index of search result for given conversation uid. If no result found return -1
170* @param uid UID of conversation being searched
171* @param model ConversationModel in which to do the lookup
172* @return an index of corresponding Conversation if any. Otherwise return -1.
173*/
174static inline int getSearchResultIndexFromUid(const QString& uid, const lrc::api::ConversationModel& model) {
175 auto it = std::find_if(model.getAllSearchResults().begin(), model.getAllSearchResults().end(),
176 [&] (const lrc::api::conversation::Info& conv) {
177 return uid == conv.uid;
178 });
179 if (it != model.getAllSearchResults().end()) {
180 return std::distance(model.getAllSearchResults().begin(), it);
181 }
182 return -1;
183}
Kateryna Kostiuk4138db12018-06-08 15:52:18 -0400184static inline bool isUrlAccessibleFromSandbox(NSURL* url)
185{
186 NSFileManager* fileManager = [[NSFileManager alloc] init];
187 NSArray* urlPathsMusic = [fileManager URLsForDirectory:NSMusicDirectory
188 inDomains:NSUserDomainMask];
189 NSArray* urlPathsPictures = [fileManager URLsForDirectory:NSPicturesDirectory
190 inDomains:NSUserDomainMask];
191 NSArray* urlPathsDownloads = [fileManager URLsForDirectory:NSDownloadsDirectory
192 inDomains:NSUserDomainMask];
193 NSArray* urlPathsMovies = [fileManager URLsForDirectory:NSMoviesDirectory
194 inDomains:NSUserDomainMask];
195 NSArray* availablePaths = [[[urlPathsMusic arrayByAddingObjectsFromArray: urlPathsPictures] arrayByAddingObjectsFromArray: urlPathsDownloads] arrayByAddingObjectsFromArray: urlPathsMovies];
196 if([availablePaths containsObject:url]) {
197 return YES;
198 }
199 for (NSURL* availableUrl in availablePaths) {
200 if ([url.path containsString:availableUrl.path]) {
201 return YES;
202 }
203 }
204 return NO;
205}
206
207static inline bool appSandboxed()
208{
209 NSString* bundleID = [[NSBundle mainBundle] bundleIdentifier];
Kateryna Kostiukb88d27f2018-06-14 12:56:52 -0400210 NSString* url = [[NSURL fileURLWithPath:NSHomeDirectory()] path];
211 NSString* appPath = [@"Library/Containers/" stringByAppendingString:bundleID];
212 if ([url containsString: appPath]) {
Kateryna Kostiuk4138db12018-06-08 15:52:18 -0400213 return YES;
214 }
215 return NO;
216}
Kateryna Kostiuk9fca5422018-11-19 16:27:46 -0500217
218static inline NSColor* colorForAccountStatus(const lrc::api::account::Status status)
219{
220 NSColor *accountStatusColor = [NSColor unregisteredColor];
221 switch (status) {
222 case lrc::api::account::Status::REGISTERED:
223 accountStatusColor = [NSColor presenceColor];
224 break;
225 case lrc::api::account::Status::TRYING:
226 accountStatusColor = [NSColor orangeColor];
227 break;
228 default:
229 break;
230 }
231 return accountStatusColor;
232}