blob: 01577ca03d6c7ed4eb446e980ff0168c7f6bc8dd [file] [log] [blame]
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -04001/*
Sébastien Blin029ffa82019-01-02 17:43:48 -05002 * Copyright (C) 2015-2019 Savoir-faire Linux Inc.
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -04003 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
4 * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21//cocoa
22#import <Quartz/Quartz.h>
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -040023#import <AVFoundation/AVFoundation.h>
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040024
25//Qt
26#import <QSize>
27#import <QtMacExtras/qmacfunctions.h>
28#import <QPixmap>
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040029#import <qstring.h>
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040030
31//LRC
32#import <api/lrc.h>
33#import <api/newaccountmodel.h>
34#import <api/newdevicemodel.h>
35#import <interfaces/pixmapmanipulatori.h>
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040036
37#import "AccSipGeneralVC.h"
38#import "views/NSColor+RingTheme.h"
39#import "views/NSImage+Extensions.h"
Kateryna Kostiuk2f2ef952019-05-07 11:04:41 -040040#import "Constants.h"
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040041
42@interface AccSipGeneralVC ()
43
44@property (unsafe_unretained) IBOutlet NSButton* photoView;
45@property (unsafe_unretained) IBOutlet NSImageView* addProfilePhotoImage;
46@property (unsafe_unretained) IBOutlet NSTextField* displayNameField;
47@property (unsafe_unretained) IBOutlet NSTextField* userNameField;
48@property (unsafe_unretained) IBOutlet NSSecureTextField* passwordField;
49@property (unsafe_unretained) IBOutlet NSTextField* proxyField;
50@property (unsafe_unretained) IBOutlet NSTextField* voicemailField;
51@property (unsafe_unretained) IBOutlet NSTextField* serverField;
52@property (unsafe_unretained) IBOutlet NSButton* removeAccountButton;
53@property (unsafe_unretained) IBOutlet NSButton* editAccountButton;
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040054@property QString selectedAccountID;
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040055
56@end
57
58@implementation AccSipGeneralVC
59
60//Tags for views
61typedef NS_ENUM(NSInteger, TagViews) {
62 DISPLAYNAME = 100
63};
64
65@synthesize accountModel;
66@synthesize delegate;
67@synthesize photoView,addProfilePhotoImage,displayNameField, userNameField, passwordField,proxyField,voicemailField, serverField, removeAccountButton, editAccountButton;
68
69-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountmodel:(lrc::api::NewAccountModel*) accountModel
70{
71 if (self = [self initWithNibName: nibNameOrNil bundle:nibBundleOrNil])
72 {
73 self.accountModel= accountModel;
74 }
75 return self;
76}
77
78-(void)viewDidLoad {
79 [super viewDidLoad];
Kateryna Kostiuka8525942018-10-17 14:33:39 -040080 [[self view] setAutoresizingMask: NSViewMinXMargin | NSViewMaxXMargin];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040081 [addProfilePhotoImage setWantsLayer: YES];
82 [self setEditingMode:NO];
83 [self updateView];
84}
85
86- (void)pictureTakerDidEnd:(IKPictureTaker *) picker
87 returnCode:(NSInteger) code
88 contextInfo:(void*) contextInfo
89{
Kateryna Kostiuk256814e2018-09-04 14:47:33 -040090 //do nothing when editing canceled
91 if (code == 0) {
92 return;
93 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040094 if (auto outputImage = [picker outputImage]) {
95 [photoView setBordered:NO];
96 auto image = [picker inputImage];
Kateryna Kostiuk2f2ef952019-05-07 11:04:41 -040097 CGFloat newSize = MIN(MIN(image.size.height, image.size.width), MAX_IMAGE_SIZE);
98 outputImage = [outputImage imageResizeInsideMax: newSize];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040099 [photoView setImage: [outputImage roundCorners: outputImage.size.height * 0.5]];
100 [addProfilePhotoImage setHidden:YES];
101 auto imageToBytes = QByteArray::fromNSData([outputImage TIFFRepresentation]).toBase64();
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400102 self.accountModel->setAvatar(self.selectedAccountID, QString(imageToBytes));
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400103 } else if(!photoView.image) {
104 [photoView setBordered:YES];
105 [addProfilePhotoImage setHidden:NO];
106 }
107}
108
109#pragma mark - NSTextFieldDelegate methods
110
111- (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
112{
113 return YES;
114}
115
116- (IBAction)triggerAdwancedSettings: (NSButton *)sender {
117 [self.delegate triggerAdvancedOptions];
118}
119
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400120- (void) setSelectedAccount:(const QString&) account {
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400121 self.selectedAccountID = account;
122 [self updateView];
123}
124
125-(void)updateView {
126 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400127 NSData *imageData = [[NSData alloc] initWithBase64EncodedString:account.profileInfo.avatar.toNSString() options:NSDataBase64DecodingIgnoreUnknownCharacters];
Kateryna Kostiuk43a79232018-10-18 15:45:18 -0400128 NSImage *image = [[NSImage alloc] initWithData:imageData];
129 if(image) {
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400130 [photoView setBordered:NO];
Kateryna Kostiuk2f2ef952019-05-07 11:04:41 -0400131 [photoView setImage: [image roundCorners: image.size.height * 0.5]];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400132 [addProfilePhotoImage setHidden:YES];
133 } else {
134 [photoView setImage:nil];
135 [photoView setBordered:YES];
136 [addProfilePhotoImage setHidden:NO];
137 }
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400138 NSString* displayName = account.profileInfo.alias.toNSString();
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400139 [displayNameField setStringValue:displayName];
140
141 NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[removeAccountButton attributedTitle]];
142 NSRange titleRange = NSMakeRange(0, [colorTitle length]);
143 [colorTitle addAttribute:NSForegroundColorAttributeName value:[NSColor errorColor] range:titleRange];
144 [removeAccountButton setAttributedTitle:colorTitle];
145 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400146 [passwordField setStringValue: accountProperties.password.toNSString()];
147 [proxyField setStringValue: accountProperties.routeset.toNSString()];
148 [userNameField setStringValue: accountProperties.username.toNSString()];
149 [serverField setStringValue: accountProperties.hostname.toNSString()];
150 [voicemailField setStringValue: accountProperties.mailbox.toNSString()];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400151 self.accountEnabled = account.enabled;
152}
153
154#pragma mark - Actions
155
156- (IBAction)editPhoto:(id)sender
157{
158 auto pictureTaker = [IKPictureTaker pictureTaker];
Kateryna Kostiukdc563242019-08-19 12:05:54 -0400159#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -0400160 if (@available(macOS 10.14, *)) {
161 AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
162 if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
163 {
164 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
165 }
166
167 if(authStatus == AVAuthorizationStatusNotDetermined)
168 {
169 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
170 if(!granted){
171 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
172 }
173 }];
174 }
175 }
Kateryna Kostiukdc563242019-08-19 12:05:54 -0400176#endif
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400177
178 [pictureTaker beginPictureTakerSheetForWindow:[self.view window]
179 withDelegate:self
180 didEndSelector:@selector(pictureTakerDidEnd:returnCode:contextInfo:)
181 contextInfo:nil];
182
183}
184
185- (IBAction)enableAccount: (NSButton *)sender {
186 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
Kateryna Kostiuk53799642019-07-30 18:21:16 -0400187 self.accountModel->setAccountEnabled(self.selectedAccountID, !account.enabled);
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400188 self.accountEnabled = account.enabled;
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400189}
190
191- (IBAction)removeAccount:(id)sender
192{
193 NSAlert *alert = [[NSAlert alloc] init];
194 [alert addButtonWithTitle:@"OK"];
Kateryna Kostiuk92a30322020-05-08 11:11:52 -0400195 [alert addButtonWithTitle:NSLocalizedString(@"Cancel", @"Button Action")];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400196 [alert setMessageText: NSLocalizedString(@"Remove account",
197 @"Remove account alert title")];
198 [alert setInformativeText:NSLocalizedString(@"By clicking \"OK\" you will remove this account on this device! This action can not be undone. Also, your registered name can be lost.",
199 @"Remove account alert message")];
200
201 if ([alert runModal] == NSAlertFirstButtonReturn) {
202 self.accountModel->removeAccount(self.selectedAccountID);
203 }
204}
205
206- (IBAction)changeEditingMode:(id)sender
207{
208 if([userNameField isEditable]) {
209 [self setEditingMode:NO];
Kateryna Kostiuke2c4e082018-10-22 16:20:22 -0400210 [self saveAccount];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400211 return;
212 }
213 [self setEditingMode:YES];
214}
215
216-(void) setEditingMode:(BOOL) shouldEdit {
217 [userNameField setEditable:shouldEdit];
218 [passwordField setEditable:shouldEdit];
219 [proxyField setEditable:shouldEdit];
220 [voicemailField setEditable:shouldEdit];
221 [serverField setEditable:shouldEdit];
222 [userNameField setDrawsBackground:!shouldEdit];
223 [passwordField setDrawsBackground:!shouldEdit];
224 [proxyField setDrawsBackground:!shouldEdit];
225 [voicemailField setDrawsBackground:!shouldEdit];
226 [serverField setDrawsBackground:!shouldEdit];
227 [userNameField setBezeled:shouldEdit];
228 [passwordField setBezeled:shouldEdit];
229 [proxyField setBezeled:shouldEdit];
230 [voicemailField setBezeled:shouldEdit];
231 [serverField setBezeled:shouldEdit];
232 if(shouldEdit) {
233 [serverField setBezelStyle:NSTextFieldSquareBezel];
234 [userNameField setBezelStyle:NSTextFieldSquareBezel];
235 [passwordField setBezelStyle:NSTextFieldSquareBezel];
236 [proxyField setBezelStyle:NSTextFieldSquareBezel];
237 [voicemailField setBezelStyle:NSTextFieldSquareBezel];
238 [userNameField becomeFirstResponder];
Kateryna Kostiuk92a30322020-05-08 11:11:52 -0400239 [editAccountButton setTitle:NSLocalizedString(@"Done", @"Edit Sip Account Action")];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400240 return;
241 }
Kateryna Kostiuk92a30322020-05-08 11:11:52 -0400242 [editAccountButton setTitle:NSLocalizedString(@"Edit Account", @"Edit Sip Account Action")];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400243 [self.view resignFirstResponder];
244}
245
246-(void) saveAccount {
247 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400248 accountProperties.hostname = QString::fromNSString(serverField.stringValue);
249 accountProperties.password = QString::fromNSString(passwordField.stringValue);
250 accountProperties.username = QString::fromNSString(userNameField.stringValue);
251 accountProperties.routeset = QString::fromNSString(proxyField.stringValue);
252 accountProperties.mailbox = QString::fromNSString(voicemailField.stringValue);
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400253 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
254}
255
256#pragma mark - NSTextFieldDelegate delegate methods
257
258- (void)controlTextDidChange:(NSNotification *)notif
259{
260 NSTextField* textField = [notif object];
261 if (textField.tag != DISPLAYNAME) {
262 return;
263 }
264 NSString* displayName = textField.stringValue;
265
266 [NSObject cancelPreviousPerformRequestsWithTarget:self];
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400267 self.accountModel->setAlias(self.selectedAccountID, QString::fromNSString(displayName));
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400268 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
269 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
270}
271
272@end