blob: 71c62b219973041def7095a66f49147651c76ab4 [file] [log] [blame]
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -04001/*
2 * Copyright (C) 2015-2018 Savoir-faire Linux Inc.
3 * 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>
29
30//LRC
31#import <api/lrc.h>
32#import <api/newaccountmodel.h>
33#import <api/newdevicemodel.h>
34#import <interfaces/pixmapmanipulatori.h>
35#import <globalinstances.h>
36
37#import "AccSipGeneralVC.h"
38#import "views/NSColor+RingTheme.h"
39#import "views/NSImage+Extensions.h"
40
41@interface AccSipGeneralVC ()
42
43@property (unsafe_unretained) IBOutlet NSButton* photoView;
44@property (unsafe_unretained) IBOutlet NSImageView* addProfilePhotoImage;
45@property (unsafe_unretained) IBOutlet NSTextField* displayNameField;
46@property (unsafe_unretained) IBOutlet NSTextField* userNameField;
47@property (unsafe_unretained) IBOutlet NSSecureTextField* passwordField;
48@property (unsafe_unretained) IBOutlet NSTextField* proxyField;
49@property (unsafe_unretained) IBOutlet NSTextField* voicemailField;
50@property (unsafe_unretained) IBOutlet NSTextField* serverField;
51@property (unsafe_unretained) IBOutlet NSButton* removeAccountButton;
52@property (unsafe_unretained) IBOutlet NSButton* editAccountButton;
53@property std::string selectedAccountID;
54
55@end
56
57@implementation AccSipGeneralVC
58
59//Tags for views
60typedef NS_ENUM(NSInteger, TagViews) {
61 DISPLAYNAME = 100
62};
63
64@synthesize accountModel;
65@synthesize delegate;
66@synthesize photoView,addProfilePhotoImage,displayNameField, userNameField, passwordField,proxyField,voicemailField, serverField, removeAccountButton, editAccountButton;
67
68-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountmodel:(lrc::api::NewAccountModel*) accountModel
69{
70 if (self = [self initWithNibName: nibNameOrNil bundle:nibBundleOrNil])
71 {
72 self.accountModel= accountModel;
73 }
74 return self;
75}
76
77-(void)viewDidLoad {
78 [super viewDidLoad];
Kateryna Kostiuk3164fb02018-08-28 17:51:43 -040079 [[self view] setAutoresizingMask: NSViewMinXMargin | NSViewMaxXMargin | NSViewHeightSizable];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040080 [photoView setBordered:YES];
81 [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];
97 CGFloat newSize = MIN(image.size.height, image.size.width);
98 outputImage = [outputImage cropImageToSize:CGSizeMake(newSize, newSize)];
99 [photoView setImage: [outputImage roundCorners: outputImage.size.height * 0.5]];
100 [addProfilePhotoImage setHidden:YES];
101 auto imageToBytes = QByteArray::fromNSData([outputImage TIFFRepresentation]).toBase64();
102 std::string imageToString = std::string(imageToBytes.constData(), imageToBytes.length());
103 self.accountModel->setAvatar(self.selectedAccountID, imageToString);
104 } else if(!photoView.image) {
105 [photoView setBordered:YES];
106 [addProfilePhotoImage setHidden:NO];
107 }
108}
109
110#pragma mark - NSTextFieldDelegate methods
111
112- (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
113{
114 return YES;
115}
116
117- (IBAction)triggerAdwancedSettings: (NSButton *)sender {
118 [self.delegate triggerAdvancedOptions];
119}
120
121- (void) setSelectedAccount:(std::string) account {
122 self.selectedAccountID = account;
123 [self updateView];
124}
125
126-(void)updateView {
127 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
128 QByteArray ba = QByteArray::fromStdString(account.profileInfo.avatar);
129
130 QVariant photo = GlobalInstances::pixmapManipulator().personPhoto(ba, nil);
131 if(QtMac::toNSImage(qvariant_cast<QPixmap>(photo))) {
132 [photoView setBordered:NO];
133 NSImage *image = QtMac::toNSImage(qvariant_cast<QPixmap>(photo));
134 CGFloat newSize = MIN(image.size.height, image.size.width);
135 image = [image cropImageToSize:CGSizeMake(newSize, newSize)];
136 [photoView setImage: [image roundCorners: image.size.height * 0.5]];
137 [addProfilePhotoImage setHidden:YES];
138 } else {
139 [photoView setImage:nil];
140 [photoView setBordered:YES];
141 [addProfilePhotoImage setHidden:NO];
142 }
143 NSString* displayName = @(account.profileInfo.alias.c_str());
144 [displayNameField setStringValue:displayName];
145
146 NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[removeAccountButton attributedTitle]];
147 NSRange titleRange = NSMakeRange(0, [colorTitle length]);
148 [colorTitle addAttribute:NSForegroundColorAttributeName value:[NSColor errorColor] range:titleRange];
149 [removeAccountButton setAttributedTitle:colorTitle];
150 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
151 [passwordField setStringValue: @(accountProperties.password.c_str())];
152 [proxyField setStringValue: @(accountProperties.routeset.c_str())];
153 [userNameField setStringValue: @(accountProperties.username.c_str())];
154 [serverField setStringValue: @(accountProperties.hostname.c_str())];
155 [voicemailField setStringValue: @(accountProperties.mailbox.c_str())];
156 self.accountEnabled = account.enabled;
157}
158
159#pragma mark - Actions
160
161- (IBAction)editPhoto:(id)sender
162{
163 auto pictureTaker = [IKPictureTaker pictureTaker];
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -0400164 if (@available(macOS 10.14, *)) {
165 AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
166 if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
167 {
168 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
169 }
170
171 if(authStatus == AVAuthorizationStatusNotDetermined)
172 {
173 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
174 if(!granted){
175 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
176 }
177 }];
178 }
179 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400180
181 [pictureTaker beginPictureTakerSheetForWindow:[self.view window]
182 withDelegate:self
183 didEndSelector:@selector(pictureTakerDidEnd:returnCode:contextInfo:)
184 contextInfo:nil];
185
186}
187
188- (IBAction)enableAccount: (NSButton *)sender {
189 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
190 self.accountModel->enableAccount(self.selectedAccountID, !account.enabled);
191 self.accountEnabled = account.enabled;
192 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
193 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
194}
195
196- (IBAction)removeAccount:(id)sender
197{
198 NSAlert *alert = [[NSAlert alloc] init];
199 [alert addButtonWithTitle:@"OK"];
200 [alert addButtonWithTitle:@"Cancel"];
201 [alert setMessageText: NSLocalizedString(@"Remove account",
202 @"Remove account alert title")];
203 [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.",
204 @"Remove account alert message")];
205
206 if ([alert runModal] == NSAlertFirstButtonReturn) {
207 self.accountModel->removeAccount(self.selectedAccountID);
208 }
209}
210
211- (IBAction)changeEditingMode:(id)sender
212{
213 if([userNameField isEditable]) {
214 [self setEditingMode:NO];
215 return;
216 }
217 [self setEditingMode:YES];
218}
219
220-(void) setEditingMode:(BOOL) shouldEdit {
221 [userNameField setEditable:shouldEdit];
222 [passwordField setEditable:shouldEdit];
223 [proxyField setEditable:shouldEdit];
224 [voicemailField setEditable:shouldEdit];
225 [serverField setEditable:shouldEdit];
226 [userNameField setDrawsBackground:!shouldEdit];
227 [passwordField setDrawsBackground:!shouldEdit];
228 [proxyField setDrawsBackground:!shouldEdit];
229 [voicemailField setDrawsBackground:!shouldEdit];
230 [serverField setDrawsBackground:!shouldEdit];
231 [userNameField setBezeled:shouldEdit];
232 [passwordField setBezeled:shouldEdit];
233 [proxyField setBezeled:shouldEdit];
234 [voicemailField setBezeled:shouldEdit];
235 [serverField setBezeled:shouldEdit];
236 if(shouldEdit) {
237 [serverField setBezelStyle:NSTextFieldSquareBezel];
238 [userNameField setBezelStyle:NSTextFieldSquareBezel];
239 [passwordField setBezelStyle:NSTextFieldSquareBezel];
240 [proxyField setBezelStyle:NSTextFieldSquareBezel];
241 [voicemailField setBezelStyle:NSTextFieldSquareBezel];
242 [userNameField becomeFirstResponder];
243 [editAccountButton setTitle:@"Done"];
244 return;
245 }
246 [self saveAccount];
247 [editAccountButton setTitle:@"Edit Account"];
248 [self.view resignFirstResponder];
249}
250
251-(void) saveAccount {
252 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
253 accountProperties.hostname = [serverField.stringValue UTF8String];
254 accountProperties.password = [passwordField.stringValue UTF8String];
255 accountProperties.username = [userNameField.stringValue UTF8String];
256 accountProperties.routeset = [proxyField.stringValue UTF8String];
257 accountProperties.mailbox = [voicemailField.stringValue UTF8String];
258 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
259}
260
261#pragma mark - NSTextFieldDelegate delegate methods
262
263- (void)controlTextDidChange:(NSNotification *)notif
264{
265 NSTextField* textField = [notif object];
266 if (textField.tag != DISPLAYNAME) {
267 return;
268 }
269 NSString* displayName = textField.stringValue;
270
271 [NSObject cancelPreviousPerformRequestsWithTarget:self];
272 self.accountModel->setAlias(self.selectedAccountID, [displayName UTF8String]);
273 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
274 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
275}
276
277@end