blob: 196560cfa0999133f6a26482396fc5e0e8f9b1fb [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/**
126 * This function return an iterator pointing to a Conversation::Info in ConversationModel given its uid. If not found
127 * the iterator is invalid thus it needs to be checked by caller.
128 * @param uid UID of conversation being searched
129 * @param model ConversationModel in which to do the lookup
130 * @return iterator pointing to corresponding Conversation if any. Points to past-the-end element otherwise.
131 */
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400132static inline lrc::api::ConversationModel::ConversationQueue::const_iterator getConversationFromUid(const QString& uid, const lrc::api::ConversationModel& model) {
Anthony Léonard6f819752018-01-05 09:53:40 -0500133 return std::find_if(model.allFilteredConversations().begin(), model.allFilteredConversations().end(),
134 [&] (const lrc::api::conversation::Info& conv) {
135 return uid == conv.uid;
136 });
137}
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400138
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500139/**
140 * This function return an iterator pointing to a Conversation::Info in ConversationModel given its participant uri. Will not work for group chat.
141 * @param uri URI of participant
142 * @param model ConversationModel in which to do the lookup
143 * @return iterator pointing to corresponding Conversation if any. Points to past-the-end element otherwise.
144 */
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400145static inline lrc::api::ConversationModel::ConversationQueue::const_iterator getConversationFromURI(const QString& uri, const lrc::api::ConversationModel& model) {
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500146 return std::find_if(model.allFilteredConversations().begin(), model.allFilteredConversations().end(),
147 [&] (const lrc::api::conversation::Info& conv) {
148 return uri == conv.participants[0];
149 });
150}
151
Kateryna Kostiuk4138db12018-06-08 15:52:18 -0400152static inline bool isUrlAccessibleFromSandbox(NSURL* url)
153{
154 NSFileManager* fileManager = [[NSFileManager alloc] init];
155 NSArray* urlPathsMusic = [fileManager URLsForDirectory:NSMusicDirectory
156 inDomains:NSUserDomainMask];
157 NSArray* urlPathsPictures = [fileManager URLsForDirectory:NSPicturesDirectory
158 inDomains:NSUserDomainMask];
159 NSArray* urlPathsDownloads = [fileManager URLsForDirectory:NSDownloadsDirectory
160 inDomains:NSUserDomainMask];
161 NSArray* urlPathsMovies = [fileManager URLsForDirectory:NSMoviesDirectory
162 inDomains:NSUserDomainMask];
163 NSArray* availablePaths = [[[urlPathsMusic arrayByAddingObjectsFromArray: urlPathsPictures] arrayByAddingObjectsFromArray: urlPathsDownloads] arrayByAddingObjectsFromArray: urlPathsMovies];
164 if([availablePaths containsObject:url]) {
165 return YES;
166 }
167 for (NSURL* availableUrl in availablePaths) {
168 if ([url.path containsString:availableUrl.path]) {
169 return YES;
170 }
171 }
172 return NO;
173}
174
175static inline bool appSandboxed()
176{
177 NSString* bundleID = [[NSBundle mainBundle] bundleIdentifier];
Kateryna Kostiukb88d27f2018-06-14 12:56:52 -0400178 NSString* url = [[NSURL fileURLWithPath:NSHomeDirectory()] path];
179 NSString* appPath = [@"Library/Containers/" stringByAppendingString:bundleID];
180 if ([url containsString: appPath]) {
Kateryna Kostiuk4138db12018-06-08 15:52:18 -0400181 return YES;
182 }
183 return NO;
184}
Kateryna Kostiuk9fca5422018-11-19 16:27:46 -0500185
186static inline NSColor* colorForAccountStatus(const lrc::api::account::Status status)
187{
188 NSColor *accountStatusColor = [NSColor unregisteredColor];
189 switch (status) {
190 case lrc::api::account::Status::REGISTERED:
191 accountStatusColor = [NSColor presenceColor];
192 break;
193 case lrc::api::account::Status::TRYING:
194 accountStatusColor = [NSColor orangeColor];
195 break;
196 default:
197 break;
198 }
199 return accountStatusColor;
200}